Commit 87412eb05be3148e812310128f361f79922baad8

Authored by Jay Berkenbilt
1 parent 3a7ee7e9

Add QPDFJob::registerProgressReporter

@@ -14,7 +14,10 @@ Next: @@ -14,7 +14,10 @@ Next:
14 14
15 Pending changes: 15 Pending changes:
16 16
17 -* Allow users to supply a custom progress reporter for QPDFJob 17 +* Allow users to supply a custom progress reporter for QPDFJob. If one
  18 + is provided, use it instead of creating one. Then expose to the C
  19 + API. Consider also exposing a way to set a new logger and to get the
  20 + logger from QPDF and QPDFJob in the C API.
18 * Check about runpath in the linux-bin distribution. I think the 21 * Check about runpath in the linux-bin distribution. I think the
19 appimage build specifically is setting the runpath, which is 22 appimage build specifically is setting the runpath, which is
20 actually desirable in this case. Make sure to understand and 23 actually desirable in this case. Make sure to understand and
include/qpdf/QPDFJob.hh
@@ -134,6 +134,14 @@ class QPDFJob @@ -134,6 +134,14 @@ class QPDFJob
134 "configure logger from getLogger() or call setLogger()")]] QPDF_DLL void 134 "configure logger from getLogger() or call setLogger()")]] QPDF_DLL void
135 setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); 135 setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
136 136
  137 + // You can register a custom progress reporter to be called by
  138 + // QPDFWriter (see QPDFWriter::registerProgressReporter). This is
  139 + // only called if you also request progress reporting through
  140 + // normal configuration methods (e.g., pass --progress, call
  141 + // config()->progress, etc.)
  142 + QPDF_DLL
  143 + void registerProgressReporter(std::function<void(int)>);
  144 +
137 // Check to make sure no contradictory options have been 145 // Check to make sure no contradictory options have been
138 // specified. This is called automatically after initializing from 146 // specified. This is called automatically after initializing from
139 // argv or json and is also called by run, but you can call it 147 // argv or json and is also called by run, but you can call it
@@ -579,6 +587,7 @@ class QPDFJob @@ -579,6 +587,7 @@ class QPDFJob
579 bool decrypt; 587 bool decrypt;
580 int split_pages; 588 int split_pages;
581 bool progress; 589 bool progress;
  590 + std::function<void(int)> progress_handler;
582 bool suppress_warnings; 591 bool suppress_warnings;
583 bool warnings_exit_zero; 592 bool warnings_exit_zero;
584 bool copy_encryption; 593 bool copy_encryption;
libqpdf/QPDFJob.cc
@@ -323,6 +323,7 @@ QPDFJob::Members::Members() : @@ -323,6 +323,7 @@ QPDFJob::Members::Members() :
323 decrypt(false), 323 decrypt(false),
324 split_pages(0), 324 split_pages(0),
325 progress(false), 325 progress(false),
  326 + progress_handler(nullptr),
326 suppress_warnings(false), 327 suppress_warnings(false),
327 warnings_exit_zero(false), 328 warnings_exit_zero(false),
328 copy_encryption(false), 329 copy_encryption(false),
@@ -464,6 +465,11 @@ QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err) @@ -464,6 +465,11 @@ QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err)
464 } 465 }
465 466
466 void 467 void
  468 +QPDFJob::registerProgressReporter(std::function<void(int)> handler) {
  469 + this->m->progress_handler = handler;
  470 +}
  471 +
  472 +void
467 QPDFJob::doIfVerbose( 473 QPDFJob::doIfVerbose(
468 std::function<void(Pipeline&, std::string const& prefix)> fn) 474 std::function<void(Pipeline&, std::string const& prefix)> fn)
469 { 475 {
@@ -3146,16 +3152,23 @@ QPDFJob::setWriterOptions(QPDF&amp; pdf, QPDFWriter&amp; w) @@ -3146,16 +3152,23 @@ QPDFJob::setWriterOptions(QPDF&amp; pdf, QPDFWriter&amp; w)
3146 w.forcePDFVersion(version, extension_level); 3152 w.forcePDFVersion(version, extension_level);
3147 } 3153 }
3148 if (m->progress) { 3154 if (m->progress) {
3149 - char const* outfilename = this->m->outfilename  
3150 - ? this->m->outfilename.get()  
3151 - : "standard output";  
3152 - w.registerProgressReporter(  
3153 - std::shared_ptr<QPDFWriter::ProgressReporter>(  
3154 - // line-break  
3155 - new ProgressReporter(  
3156 - *this->m->log->getInfo(),  
3157 - this->m->message_prefix,  
3158 - outfilename))); 3155 + if (this->m->progress_handler) {
  3156 + w.registerProgressReporter(
  3157 + std::shared_ptr<QPDFWriter::ProgressReporter>(
  3158 + new QPDFWriter::FunctionProgressReporter(
  3159 + this->m->progress_handler)));
  3160 + } else {
  3161 + char const* outfilename = this->m->outfilename
  3162 + ? this->m->outfilename.get()
  3163 + : "standard output";
  3164 + w.registerProgressReporter(
  3165 + std::shared_ptr<QPDFWriter::ProgressReporter>(
  3166 + // line-break
  3167 + new ProgressReporter(
  3168 + *this->m->log->getInfo(),
  3169 + this->m->message_prefix,
  3170 + outfilename)));
  3171 + }
3159 } 3172 }
3160 } 3173 }
3161 3174
qpdf/qtest/qpdf/filter-progress.pl
@@ -4,10 +4,15 @@ use warnings; @@ -4,10 +4,15 @@ use warnings;
4 my $seen = 0; 4 my $seen = 0;
5 while (<>) 5 while (<>)
6 { 6 {
7 - if (m/write progress: (?:10)?0\%/) 7 + if (m/write progress: 0\%/)
8 { 8 {
9 print; 9 print;
10 } 10 }
  11 + elsif (m/write progress: 100\%/)
  12 + {
  13 + print;
  14 + $seen = 0;
  15 + }
11 elsif (m/write progress: /) 16 elsif (m/write progress: /)
12 { 17 {
13 if (! $seen) 18 if (! $seen)
qpdf/qtest/qpdf/job-api.out
1 normal 1 normal
  2 +qpdf: a.pdf: write progress: 0%
  3 +....other write progress....
  4 +qpdf: a.pdf: write progress: 100%
  5 +custom progress reporter
  6 +custom write progress: 0%
  7 +....other write progress....
  8 +custom write progress: 100%
2 error caught by check 9 error caught by check
3 finished config 10 finished config
4 usage: an input file name is required 11 usage: an input file name is required
qpdf/qtest/qpdfjob.test
@@ -87,7 +87,8 @@ $td-&gt;runtest(&quot;QPDFJob json partial&quot;, @@ -87,7 +87,8 @@ $td-&gt;runtest(&quot;QPDFJob json partial&quot;,
87 {$td->FILE => "job-partial-json.out", $td->EXIT_STATUS => 0}, 87 {$td->FILE => "job-partial-json.out", $td->EXIT_STATUS => 0},
88 $td->NORMALIZE_NEWLINES); 88 $td->NORMALIZE_NEWLINES);
89 $td->runtest("QPDFJob API", 89 $td->runtest("QPDFJob API",
90 - {$td->COMMAND => "test_driver 84 -"}, 90 + {$td->COMMAND => "test_driver 84 -",
  91 + $td->FILTER => "perl filter-progress.pl"},
91 {$td->FILE => "job-api.out", $td->EXIT_STATUS => 0}, 92 {$td->FILE => "job-api.out", $td->EXIT_STATUS => 0},
92 $td->NORMALIZE_NEWLINES); 93 $td->NORMALIZE_NEWLINES);
93 $td->runtest("check output", 94 $td->runtest("check output",
qpdf/test_driver.cc
@@ -2937,6 +2937,27 @@ test_84(QPDF&amp; pdf, char const* arg2) @@ -2937,6 +2937,27 @@ test_84(QPDF&amp; pdf, char const* arg2)
2937 ->qdf() 2937 ->qdf()
2938 ->deterministicId() 2938 ->deterministicId()
2939 ->objectStreams("preserve") 2939 ->objectStreams("preserve")
  2940 + ->progress()
  2941 + ->checkConfiguration();
  2942 + j.run();
  2943 + assert(j.getExitCode() == 0);
  2944 + assert(!j.hasWarnings());
  2945 + assert(j.getEncryptionStatus() == 0);
  2946 + }
  2947 +
  2948 + std::cout << "custom progress reporter" << std::endl;
  2949 + {
  2950 + QPDFJob j;
  2951 + j.registerProgressReporter([](int p) {
  2952 + std::cout << "custom write progress: " << p << "%" << std::endl;
  2953 + });
  2954 + j.config()
  2955 + ->inputFile("minimal.pdf")
  2956 + ->outputFile("a.pdf")
  2957 + ->qdf()
  2958 + ->deterministicId()
  2959 + ->objectStreams("preserve")
  2960 + ->progress()
2940 ->checkConfiguration(); 2961 ->checkConfiguration();
2941 j.run(); 2962 j.run();
2942 assert(j.getExitCode() == 0); 2963 assert(j.getExitCode() == 0);