summaryrefslogtreecommitdiffstats
path: root/src/printsupport/kernel/qprinter.cpp
diff options
context:
space:
mode:
authorJohn Layt <jlayt@kde.org>2013-11-23 19:52:34 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-29 15:59:00 +0100
commite8a45152b5e2e99e757e91a5d42a6dce609ff583 (patch)
treead9b801d10b236a4d74caa58b270475b7f25b85b /src/printsupport/kernel/qprinter.cpp
parent7079f1121325cedfb59c753870bd227a897ce6c7 (diff)
QPrinter - Fix OutputFormat when no printers
Currently the QPrinter constructor, setOutputFormat() and setPrinterName() make bad assumptions about the availability of printers when configuring NativeFormat which can lead to inconsistent print engine set-ups leading to crashes in the print dialog, especially on Windows where a valid DEVMODE is needed. This change cleans up the init and methods to ensure NativeFormat can only ever be set if we have both a valid plugin and a valid printer, if not the PdfFormat is used. One side-effect of this is that it is now impossible to set an invalid printer name via QPrinter (but still able to be done via QPrintEngine if really needed). Also if no default printer is set then use the first available one. This also fixes a bug where setting a new printer name on Windows reset all the saved settings. [ChangeLog][Important Behavior Changes] QPrinter no longer allows you to set an invalid printer name. Task-number: QTBUG-34345 Task-number: QTBUG-26008 Task-number: QTBUG-26430 Change-Id: I19737e4209d8c8df5817ea83246b3dd0c483ee85 Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src/printsupport/kernel/qprinter.cpp')
-rw-r--r--src/printsupport/kernel/qprinter.cpp171
1 files changed, 109 insertions, 62 deletions
diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp
index 819f9343f7..0c08e44617 100644
--- a/src/printsupport/kernel/qprinter.cpp
+++ b/src/printsupport/kernel/qprinter.cpp
@@ -48,7 +48,6 @@
#include <qpa/qplatformprintersupport.h>
#include "qprintengine.h"
-#include "qprinterinfo.h"
#include "qlist.h"
#include <qcoreapplication.h>
#include <qfileinfo.h>
@@ -163,10 +162,39 @@ Q_PRINTSUPPORT_EXPORT QSizeF qt_printerPaperSize(QPrinter::Orientation orientati
(qt_paperSizes[paperSize][height_index] * 72 / 25.4) / multiplier);
}
-void QPrinterPrivate::createDefaultEngines()
+QPrinterInfo QPrinterPrivate::findValidPrinter(const QPrinterInfo &printer)
{
- QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
- if (outputFormat == QPrinter::NativeFormat && ps) {
+ // Try find a valid printer to use, either the one given, the default or the first available
+ QPrinterInfo printerToUse = printer;
+ if (printerToUse.isNull()) {
+ printerToUse = QPrinterInfo::defaultPrinter();
+ if (printerToUse.isNull()) {
+ QList<QPrinterInfo> availablePrinters = QPrinterInfo::availablePrinters();
+ if (!availablePrinters.isEmpty())
+ printerToUse = availablePrinters.at(0);
+ }
+ }
+ return printerToUse;
+}
+
+void QPrinterPrivate::initEngines(QPrinter::OutputFormat format, const QPrinterInfo &printer)
+{
+ // Default to PdfFormat
+ outputFormat = QPrinter::PdfFormat;
+ QPlatformPrinterSupport *ps = 0;
+ QString printerName;
+
+ // Only set NativeFormat if we have a valid plugin and printer to use
+ if (format == QPrinter::NativeFormat) {
+ ps = QPlatformPrinterSupportPlugin::get();
+ QPrinterInfo printerToUse = findValidPrinter(printer);
+ if (ps && !printerToUse.isNull()) {
+ outputFormat = QPrinter::NativeFormat;
+ printerName = printerToUse.printerName();
+ }
+ }
+
+ if (outputFormat == QPrinter::NativeFormat) {
printEngine = ps->createNativePrintEngine(printerMode);
paintEngine = ps->createPaintEngine(printEngine, printerMode);
} else {
@@ -174,8 +202,42 @@ void QPrinterPrivate::createDefaultEngines()
paintEngine = pdfEngine;
printEngine = pdfEngine;
}
+
use_default_engine = true;
had_default_engines = true;
+ printEngine->setProperty(QPrintEngine::PPK_PrinterName, printerName);
+ addToManualSetList(QPrintEngine::PPK_PrinterName);
+ validPrinter = true;
+}
+
+void QPrinterPrivate::changeEngines(QPrinter::OutputFormat format, const QPrinterInfo &printer)
+{
+ QPrintEngine *oldPrintEngine = printEngine;
+ const bool def_engine = use_default_engine;
+
+ initEngines(format, printer);
+
+ if (oldPrintEngine) {
+ for (int i = 0; i < manualSetList.size(); ++i) {
+ QPrintEngine::PrintEnginePropertyKey key = manualSetList[i];
+ QVariant prop;
+ // PPK_NumberOfCopies need special treatmeant since it in most cases
+ // will return 1, disregarding the actual value that was set
+ // PPK_PrinterName also needs special treatment as initEngines has set it already
+ if (key == QPrintEngine::PPK_NumberOfCopies)
+ prop = QVariant(q_ptr->copyCount());
+ else if (key != QPrintEngine::PPK_PrinterName)
+ prop = oldPrintEngine->property(key);
+
+ if (prop.isValid()) {
+ printEngine->setProperty(key, prop);
+ addToManualSetList(key);
+ }
+ }
+ }
+
+ if (def_engine)
+ delete oldPrintEngine;
}
#ifndef QT_NO_PRINTPREVIEWWIDGET
@@ -510,13 +572,7 @@ QPrinter::QPrinter(PrinterMode mode)
: QPagedPaintDevice(),
d_ptr(new QPrinterPrivate(this))
{
- d_ptr->init(mode);
- QPrinterInfo defPrn(QPrinterInfo::defaultPrinter());
- if (!defPrn.isNull()) {
- setPrinterName(defPrn.printerName());
- } else if (QPrinterInfo::availablePrinters().isEmpty()) {
- setOutputFormat(QPrinter::PdfFormat);
- }
+ d_ptr->init(QPrinterInfo(), mode);
}
/*!
@@ -528,11 +584,10 @@ QPrinter::QPrinter(const QPrinterInfo& printer, PrinterMode mode)
: QPagedPaintDevice(),
d_ptr(new QPrinterPrivate(this))
{
- d_ptr->init(mode);
- setPrinterName(printer.printerName());
+ d_ptr->init(printer, mode);
}
-void QPrinterPrivate::init(QPrinter::PrinterMode mode)
+void QPrinterPrivate::init(const QPrinterInfo &printer, QPrinter::PrinterMode mode)
{
if (!QCoreApplication::instance()) {
qFatal("QPrinter: Must construct a QCoreApplication before a QPrinter");
@@ -540,14 +595,8 @@ void QPrinterPrivate::init(QPrinter::PrinterMode mode)
}
printerMode = mode;
- outputFormat = QPrinter::NativeFormat;
- createDefaultEngines();
-#ifndef QT_NO_PRINTPREVIEWWIDGET
- previewEngine = 0;
-#endif
- realPrintEngine = 0;
- realPaintEngine = 0;
+ initEngines(QPrinter::NativeFormat, printer);
}
/*!
@@ -612,40 +661,30 @@ QPrinter::~QPrinter()
\since 4.1
Sets the output format for this printer to \a format.
+
+ If \a format is the same value as currently set then no change will be made.
+
+ If \a format is NativeFormat then the printerName will be set to the default
+ printer. If there are no valid printers configured then no change will be made.
+ If you want to set NativeFormat with a specific printerName then use
+ setPrinterName().
+
+ \sa setPrinterName()
*/
void QPrinter::setOutputFormat(OutputFormat format)
{
Q_D(QPrinter);
- if (d->validPrinter && d->outputFormat == format)
- return;
- d->outputFormat = format;
-
- QPrintEngine *oldPrintEngine = d->printEngine;
- const bool def_engine = d->use_default_engine;
- d->printEngine = 0;
- d->createDefaultEngines();
+ if (d->outputFormat == format)
+ return;
- if (oldPrintEngine) {
- for (int i = 0; i < d->manualSetList.size(); ++i) {
- QPrintEngine::PrintEnginePropertyKey key = d->manualSetList[i];
- QVariant prop;
- // PPK_NumberOfCopies need special treatmeant since it in most cases
- // will return 1, disregarding the actual value that was set
- if (key == QPrintEngine::PPK_NumberOfCopies)
- prop = QVariant(copyCount());
- else
- prop = oldPrintEngine->property(key);
- if (prop.isValid())
- d->printEngine->setProperty(key, prop);
- }
+ if (format == QPrinter::NativeFormat) {
+ QPrinterInfo printerToUse = d->findValidPrinter();
+ if (!printerToUse.isNull())
+ d->changeEngines(format, printerToUse);
+ } else {
+ d->changeEngines(format, QPrinterInfo());
}
-
- if (def_engine)
- delete oldPrintEngine;
-
- if (d->outputFormat == QPrinter::PdfFormat)
- d->validPrinter = true;
}
/*!
@@ -683,30 +722,38 @@ QString QPrinter::printerName() const
/*!
Sets the printer name to \a name.
- \sa printerName(), isValid()
+ If the \a name is empty then the output format will be set to PdfFormat.
+
+ If the \a name is not a valid printer then no change will be made.
+
+ If the \a name is a valid printer then the output format will be set to NativeFormat.
+
+ \sa printerName(), isValid(), setOutputFormat()
*/
void QPrinter::setPrinterName(const QString &name)
{
Q_D(QPrinter);
ABORT_IF_ACTIVE("QPrinter::setPrinterName");
- QList<QPrinterInfo> prnList = QPrinterInfo::availablePrinters();
+ if (printerName() == name)
+ return;
+
if (name.isEmpty()) {
- d->validPrinter = d->outputFormat == QPrinter::PdfFormat;
- } else {
- d->validPrinter = false;
- for (int i = 0; i < prnList.size(); ++i) {
- if (prnList[i].printerName() == name) {
- d->validPrinter = true;
- break;
- }
- }
+ setOutputFormat(QPrinter::PdfFormat);
+ return;
}
- d->printEngine->setProperty(QPrintEngine::PPK_PrinterName, name);
- d->addToManualSetList(QPrintEngine::PPK_PrinterName);
-}
+ QPrinterInfo printerToUse = QPrinterInfo::printerInfo(name);
+ if (printerToUse.isNull())
+ return;
+ if (outputFormat() == QPrinter::PdfFormat) {
+ d->changeEngines(QPrinter::NativeFormat, printerToUse);
+ } else {
+ d->printEngine->setProperty(QPrintEngine::PPK_PrinterName, name);
+ d->addToManualSetList(QPrintEngine::PPK_PrinterName);
+ }
+}
/*!
\since 4.4