KDEPrint and CUPS: Where the Options Go
I was chasing a printing bug because the application appeared to ignore duplex selection. The drawing code was innocent. The useful clue was that printing to a PostScript file worked while the CUPS queue did not apply the requested option.
KDEPrint sits between the application and the print system. The application paints pages through Qt’s printer interface, KDEPrint presents the common and driver-specific choices, and the selected backend submits the resulting job. With CUPS, queue capabilities and options come from CUPS rather than being invented by every application.
For an application, the core remains ordinary painting:
KPrinter printer;
if (printer.setup(this)) {
QPainter painter(&printer);
painter.drawText(72, 72, "Printer test");
painter.end();
}
The setup dialog gathers destination, page range, copies, and available properties. KPrinter then carries those choices into the KDEPrint path. The application’s responsibility is to paginate correctly and draw each requested page. It should not run lpr itself and then wonder why the desktop’s settings vanished.
When options misbehave, I now separate the stages. First I print to a file and inspect whether the PostScript pages are sane. Next I check the queue and its advertised defaults:
lpstat -p -d
lpoptions -p office -l
Then I submit a small known document directly with lp to see whether CUPS and the printer agree without the application involved. This distinguishes a rendering defect from a queue, PPD, filter, or device problem.
Driver-specific settings deserve some humility. Duplex names, available resolutions, and media trays are described by the printer’s PPD and may differ across queues. Hard-coding one printer’s option into application code is therefore both fragile and impolite. KDEPrint already has the unenviable job of asking the printer what it thinks it can do.
Page ranges require coordination with the application. If the print dialog says pages 3 through 5, my painting loop must honor the values reported by the printer object and call newPage() between pages. I test one page, a middle range, reverse order when offered, and several copies. These cases expose off-by-one errors that a ten-page full print politely hides under ten sheets of paper.
I also end the painter explicitly before inspecting the job. That completes PostScript generation and lets the backend submit a finished stream. Error reporting after setup deserves attention; cancellation from the dialog is not the same event as a backend rejecting a job.
I prefer letting KDEPrint expose those details and keeping application settings limited to document matters. The caveat is that a successful job submission only means the print system accepted responsibility. It does not mean paper will emerge. Printers retain a small but determined independence from software engineering.