diff options
Diffstat (limited to 'src/printsupport/kernel')
22 files changed, 6991 insertions, 0 deletions
diff --git a/src/printsupport/kernel/kernel.pri b/src/printsupport/kernel/kernel.pri new file mode 100644 index 0000000000..3868d9e212 --- /dev/null +++ b/src/printsupport/kernel/kernel.pri @@ -0,0 +1,34 @@ +HEADERS += \ + $$PWD/qpaintengine_alpha_p.h \ + $$PWD/qpaintengine_preview_p.h \ + $$PWD/qprintengine.h \ + $$PWD/qprinter.h \ + $$PWD/qprinter_p.h \ + $$PWD/qprinterinfo.h \ + $$PWD/qprinterinfo_p.h \ + $$PWD/qplatformprintplugin_qpa.h \ + $$PWD/qplatformprintersupport_qpa.h + +SOURCES += \ + $$PWD/qpaintengine_alpha.cpp \ + $$PWD/qpaintengine_preview.cpp \ + $$PWD/qprintengine_pdf.cpp \ + $$PWD/qprinter.cpp \ + $$PWD/qprinterinfo.cpp \ + $$PWD/qplatformprintplugin.cpp \ + $$PWD/qplatformprintersupport_qpa.cpp + +unix:!symbian { + HEADERS += \ + $$PWD/qprinterinfo_unix_p.h + SOURCES += \ + $$PWD/qprinterinfo_unix.cpp +} + + +x11|qpa:!win32 { + SOURCES += $$PWD/qcups.cpp + HEADERS += $$PWD/qcups_p.h +} else { + DEFINES += QT_NO_CUPS QT_NO_LPR +} diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp new file mode 100644 index 0000000000..76050d9d71 --- /dev/null +++ b/src/printsupport/kernel/qcups.cpp @@ -0,0 +1,446 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <qdebug.h> +#include "qcups_p.h" +#include "qprinterinfo_unix_p.h" + +#ifndef QT_NO_CUPS + +#ifndef QT_LINUXBASE // LSB merges everything into cups.h +# include <cups/language.h> +#endif +#include <qtextcodec.h> + +QT_BEGIN_NAMESPACE + +typedef int (*CupsGetDests)(cups_dest_t **dests); +typedef void (*CupsFreeDests)(int num_dests, cups_dest_t *dests); +typedef const char* (*CupsGetPPD)(const char *printer); +typedef int (*CupsMarkOptions)(ppd_file_t *ppd, int num_options, cups_option_t *options); +typedef ppd_file_t* (*PPDOpenFile)(const char *filename); +typedef void (*PPDMarkDefaults)(ppd_file_t *ppd); +typedef int (*PPDMarkOption)(ppd_file_t *ppd, const char *keyword, const char *option); +typedef void (*PPDClose)(ppd_file_t *ppd); +typedef int (*PPDMarkOption)(ppd_file_t *ppd, const char *keyword, const char *option); +typedef void (*CupsFreeOptions)(int num_options, cups_option_t *options); +typedef void (*CupsSetDests)(int num_dests, cups_dest_t *dests); +typedef cups_lang_t* (*CupsLangGet)(const char *language); +typedef const char* (*CupsLangEncoding)(cups_lang_t *language); +typedef int (*CupsAddOption)(const char *name, const char *value, int num_options, cups_option_t **options); +typedef int (*CupsTempFd)(char *name, int len); +typedef int (*CupsPrintFile)(const char * name, const char * filename, const char * title, int num_options, cups_option_t * options); + +static bool cupsLoaded = false; +static int qt_cups_num_printers = 0; +static CupsGetDests _cupsGetDests = 0; +static CupsFreeDests _cupsFreeDests = 0; +static CupsGetPPD _cupsGetPPD = 0; +static PPDOpenFile _ppdOpenFile = 0; +static PPDMarkDefaults _ppdMarkDefaults = 0; +static PPDClose _ppdClose = 0; +static CupsMarkOptions _cupsMarkOptions = 0; +static PPDMarkOption _ppdMarkOption = 0; +static CupsFreeOptions _cupsFreeOptions = 0; +static CupsSetDests _cupsSetDests = 0; +static CupsLangGet _cupsLangGet = 0; +static CupsLangEncoding _cupsLangEncoding = 0; +static CupsAddOption _cupsAddOption = 0; +static CupsTempFd _cupsTempFd = 0; +static CupsPrintFile _cupsPrintFile = 0; + +static void resolveCups() +{ + QLibrary cupsLib(QLatin1String("cups"), 2); + if(cupsLib.load()) { + _cupsGetDests = (CupsGetDests) cupsLib.resolve("cupsGetDests"); + _cupsFreeDests = (CupsFreeDests) cupsLib.resolve("cupsFreeDests"); + _cupsGetPPD = (CupsGetPPD) cupsLib.resolve("cupsGetPPD"); + _cupsLangGet = (CupsLangGet) cupsLib.resolve("cupsLangGet"); + _cupsLangEncoding = (CupsLangEncoding) cupsLib.resolve("cupsLangEncoding"); + _ppdOpenFile = (PPDOpenFile) cupsLib.resolve("ppdOpenFile"); + _ppdMarkDefaults = (PPDMarkDefaults) cupsLib.resolve("ppdMarkDefaults"); + _ppdClose = (PPDClose) cupsLib.resolve("ppdClose"); + _cupsMarkOptions = (CupsMarkOptions) cupsLib.resolve("cupsMarkOptions"); + _ppdMarkOption = (PPDMarkOption) cupsLib.resolve("ppdMarkOption"); + _cupsFreeOptions = (CupsFreeOptions) cupsLib.resolve("cupsFreeOptions"); + _cupsSetDests = (CupsSetDests) cupsLib.resolve("cupsSetDests"); + _cupsAddOption = (CupsAddOption) cupsLib.resolve("cupsAddOption"); + _cupsTempFd = (CupsTempFd) cupsLib.resolve("cupsTempFd"); + _cupsPrintFile = (CupsPrintFile) cupsLib.resolve("cupsPrintFile"); + + if (_cupsGetDests && _cupsFreeDests) { + cups_dest_t *printers; + int num_printers = _cupsGetDests(&printers); + if (num_printers) + _cupsFreeDests(num_printers, printers); + qt_cups_num_printers = num_printers; + } + } + cupsLoaded = true; +} + +// ================ CUPS Support class ======================== + +QCUPSSupport::QCUPSSupport() + : + prnCount(0), + printers(0), + page_sizes(0), + currPrinterIndex(0), + currPPD(0) +{ + if (!cupsLoaded) + resolveCups(); + + // getting all available printers + if (!isAvailable()) + return; + + prnCount = _cupsGetDests(&printers); + + for (int i = 0; i < prnCount; ++i) { + if (printers[i].is_default) { + currPrinterIndex = i; + setCurrentPrinter(i); + break; + } + } + +#ifndef QT_NO_TEXTCODEC + cups_lang_t *cupsLang = _cupsLangGet(0); + codec = QTextCodec::codecForName(_cupsLangEncoding(cupsLang)); + if (!codec) + codec = QTextCodec::codecForLocale(); +#endif +} + +QCUPSSupport::~QCUPSSupport() +{ + if (currPPD) + _ppdClose(currPPD); + if (prnCount) + _cupsFreeDests(prnCount, printers); +} + +int QCUPSSupport::availablePrintersCount() const +{ + return prnCount; +} + +const cups_dest_t* QCUPSSupport::availablePrinters() const +{ + return printers; +} + +const ppd_file_t* QCUPSSupport::currentPPD() const +{ + return currPPD; +} + +const ppd_file_t* QCUPSSupport::setCurrentPrinter(int index) +{ + Q_ASSERT(index >= 0 && index <= prnCount); + if (index == prnCount) + return 0; + + currPrinterIndex = index; + + if (currPPD) + _ppdClose(currPPD); + currPPD = 0; + page_sizes = 0; + + const char *ppdFile = _cupsGetPPD(printers[index].name); + + if (!ppdFile) + return 0; + + currPPD = _ppdOpenFile(ppdFile); + unlink(ppdFile); + + // marking default options + _ppdMarkDefaults(currPPD); + + // marking options explicitly set + _cupsMarkOptions(currPPD, printers[currPrinterIndex].num_options, printers[currPrinterIndex].options); + + // getting pointer to page sizes + page_sizes = ppdOption("PageSize"); + + return currPPD; +} + +int QCUPSSupport::currentPrinterIndex() const +{ + return currPrinterIndex; +} + +bool QCUPSSupport::isAvailable() +{ + if(!cupsLoaded) + resolveCups(); + + return _cupsGetDests && + _cupsFreeDests && + _cupsGetPPD && + _ppdOpenFile && + _ppdMarkDefaults && + _ppdClose && + _cupsMarkOptions && + _ppdMarkOption && + _cupsFreeOptions && + _cupsSetDests && + _cupsLangGet && + _cupsLangEncoding && + _cupsAddOption && + (qt_cups_num_printers > 0); +} + +const ppd_option_t* QCUPSSupport::ppdOption(const char *key) const +{ + if (currPPD) { + for (int gr = 0; gr < currPPD->num_groups; ++gr) { + for (int opt = 0; opt < currPPD->groups[gr].num_options; ++opt) { + if (qstrcmp(currPPD->groups[gr].options[opt].keyword, key) == 0) + return &currPPD->groups[gr].options[opt]; + } + } + } + return 0; +} + +const cups_option_t* QCUPSSupport::printerOption(const QString &key) const +{ + for (int i = 0; i < printers[currPrinterIndex].num_options; ++i) { + if (QLatin1String(printers[currPrinterIndex].options[i].name) == key) + return &printers[currPrinterIndex].options[i]; + } + return 0; +} + +const ppd_option_t* QCUPSSupport::pageSizes() const +{ + return page_sizes; +} + +int QCUPSSupport::markOption(const char* name, const char* value) +{ + return _ppdMarkOption(currPPD, name, value); +} + +void QCUPSSupport::saveOptions(QList<const ppd_option_t*> options, QList<const char*> markedOptions) +{ + int oldOptionCount = printers[currPrinterIndex].num_options; + cups_option_t* oldOptions = printers[currPrinterIndex].options; + + int newOptionCount = 0; + cups_option_t* newOptions = 0; + + // copying old options that are not on the new list + for (int i = 0; i < oldOptionCount; ++i) { + bool contains = false; + for (int j = 0; j < options.count(); ++j) { + if (qstrcmp(options.at(j)->keyword, oldOptions[i].name) == 0) { + contains = true; + break; + } + } + + if (!contains) { + newOptionCount = _cupsAddOption(oldOptions[i].name, oldOptions[i].value, newOptionCount, &newOptions); + } + } + + // we can release old option list + _cupsFreeOptions(oldOptionCount, oldOptions); + + // adding marked options + for (int i = 0; i < markedOptions.count(); ++i) { + const char* name = markedOptions.at(i); + ++i; + newOptionCount = _cupsAddOption(name, markedOptions.at(i), newOptionCount, &newOptions); + } + + // placing the new option list + printers[currPrinterIndex].num_options = newOptionCount; + printers[currPrinterIndex].options = newOptions; + + // saving new default values + _cupsSetDests(prnCount, printers); +} + +QRect QCUPSSupport::paperRect(const char *choice) const +{ + if (!currPPD) + return QRect(); + for (int i = 0; i < currPPD->num_sizes; ++i) { + if (qstrcmp(currPPD->sizes[i].name, choice) == 0) + return QRect(0, 0, qRound(currPPD->sizes[i].width), qRound(currPPD->sizes[i].length)); + } + return QRect(); +} + +QRect QCUPSSupport::pageRect(const char *choice) const +{ + if (!currPPD) + return QRect(); + for (int i = 0; i < currPPD->num_sizes; ++i) { + if (qstrcmp(currPPD->sizes[i].name, choice) == 0) + return QRect(qRound(currPPD->sizes[i].left), + qRound(currPPD->sizes[i].length - currPPD->sizes[i].top), + qRound(currPPD->sizes[i].right - currPPD->sizes[i].left), + qRound(currPPD->sizes[i].top - currPPD->sizes[i].bottom)); + } + return QRect(); +} + +QStringList QCUPSSupport::options() const +{ + QStringList list; + collectMarkedOptions(list); + return list; +} + +bool QCUPSSupport::printerHasPPD(const char *printerName) +{ + if (!isAvailable()) + return false; + const char *ppdFile = _cupsGetPPD(printerName); + if (ppdFile) + unlink(ppdFile); + return (ppdFile != 0); +} + +QString QCUPSSupport::unicodeString(const char *s) +{ +#ifndef QT_NO_TEXTCODEC + return codec->toUnicode(s); +#else + return QLatin1String(s); +#endif +} + +void QCUPSSupport::collectMarkedOptions(QStringList& list, const ppd_group_t* group) const +{ + if (group == 0) { + if (!currPPD) + return; + for (int i = 0; i < currPPD->num_groups; ++i) { + collectMarkedOptions(list, &currPPD->groups[i]); + collectMarkedOptionsHelper(list, &currPPD->groups[i]); + } + } else { + for (int i = 0; i < group->num_subgroups; ++i) + collectMarkedOptionsHelper(list, &group->subgroups[i]); + } +} + +void QCUPSSupport::collectMarkedOptionsHelper(QStringList& list, const ppd_group_t* group) const +{ + for (int i = 0; i < group->num_options; ++i) { + for (int j = 0; j < group->options[i].num_choices; ++j) { + if (group->options[i].choices[j].marked == 1 && qstrcmp(group->options[i].choices[j].choice, group->options[i].defchoice) != 0) + list << QString::fromLocal8Bit(group->options[i].keyword) << QString::fromLocal8Bit(group->options[i].choices[j].choice); + } + } +} + +QPair<int, QString> QCUPSSupport::tempFd() +{ + char filename[512]; + int fd = _cupsTempFd(filename, 512); + return QPair<int, QString>(fd, QString::fromLocal8Bit(filename)); +} + +// Prints the given file and returns a job id. +int QCUPSSupport::printFile(const char * printerName, const char * filename, const char * title, + int num_options, cups_option_t * options) +{ + return _cupsPrintFile(printerName, filename, title, num_options, options); +} + +QCUPSSupport::Printer::Printer(const QString &n) : name(n), isDefault(false), cupsPrinterIndex(-1) +{ +} + +QList<QCUPSSupport::Printer> QCUPSSupport::availableUnixPrinters() +{ + QList<Printer> printers; + +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + if (QCUPSSupport::isAvailable()) { + QCUPSSupport cups; + int cupsPrinterCount = cups.availablePrintersCount(); + const cups_dest_t* cupsPrinters = cups.availablePrinters(); + for (int i = 0; i < cupsPrinterCount; ++i) { + QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name)); + if (cupsPrinters[i].instance) + printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance); + + Printer p(printerName); + if (cupsPrinters[i].is_default) + p.isDefault = true; + p.cupsPrinterIndex = i; + printers.append(p); + } + } else +#endif + { + QList<QPrinterDescription> lprPrinters; + int defprn = qt_getLprPrinters(lprPrinters); + // populating printer combo + foreach (const QPrinterDescription &description, lprPrinters) + printers.append(Printer(description.name)); + if (defprn >= 0 && defprn < printers.size()) + printers[defprn].isDefault = true; + } + + return printers; +} + +QList<QPrinter::PaperSize> QCUPSSupport::getCupsPrinterPaperSizes(int cupsPrinterIndex) +{ + return qt_getCupsPrinterPaperSizes(cupsPrinterIndex); +} + +QT_END_NAMESPACE + +#endif // QT_NO_CUPS diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h new file mode 100644 index 0000000000..cb7a79e486 --- /dev/null +++ b/src/printsupport/kernel/qcups_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCUPS_P_H +#define QCUPS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include "QtCore/qstring.h" +#include "QtCore/qstringlist.h" +#include "QtCore/qpair.h" +#include "QtPrintSupport/qprinter.h" + +#ifndef QT_NO_CUPS +#include <QtCore/qlibrary.h> +#include <cups/cups.h> +#include <cups/ppd.h> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_TYPEINFO(cups_option_t, Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE); + +class Q_PRINTSUPPORT_EXPORT QCUPSSupport +{ +public: + struct Printer + { + Printer(const QString &name = QString()); + + QString name; + bool isDefault; + int cupsPrinterIndex; + }; + QCUPSSupport(); + ~QCUPSSupport(); + + static bool isAvailable(); + static int cupsVersion() { return isAvailable() ? CUPS_VERSION_MAJOR*10000+CUPS_VERSION_MINOR*100+CUPS_VERSION_PATCH : 0; } + int availablePrintersCount() const; + const cups_dest_t* availablePrinters() const; + int currentPrinterIndex() const; + const ppd_file_t* setCurrentPrinter(int index); + + const ppd_file_t* currentPPD() const; + const ppd_option_t* ppdOption(const char *key) const; + + const cups_option_t* printerOption(const QString &key) const; + const ppd_option_t* pageSizes() const; + + int markOption(const char* name, const char* value); + void saveOptions(QList<const ppd_option_t*> options, QList<const char*> markedOptions); + + QRect paperRect(const char *choice) const; + QRect pageRect(const char *choice) const; + + QStringList options() const; + + static bool printerHasPPD(const char *printerName); + + QString unicodeString(const char *s); + + QPair<int, QString> tempFd(); + int printFile(const char * printerName, const char * filename, const char * title, + int num_options, cups_option_t * options); + + static QList<Printer> availableUnixPrinters(); + static QList<QPrinter::PaperSize> getCupsPrinterPaperSizes(int cupsPrinterIndex); + +private: + void collectMarkedOptions(QStringList& list, const ppd_group_t* group = 0) const; + void collectMarkedOptionsHelper(QStringList& list, const ppd_group_t* group) const; + + int prnCount; + cups_dest_t *printers; + const ppd_option_t* page_sizes; + int currPrinterIndex; + ppd_file_t *currPPD; +#ifndef QT_NO_TEXTCODEC + QTextCodec *codec; +#endif +}; + +QT_END_NAMESPACE + +#endif // QT_NO_CUPS + +#endif diff --git a/src/printsupport/kernel/qpaintengine_alpha.cpp b/src/printsupport/kernel/qpaintengine_alpha.cpp new file mode 100644 index 0000000000..beda2c7144 --- /dev/null +++ b/src/printsupport/kernel/qpaintengine_alpha.cpp @@ -0,0 +1,516 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qglobal.h> + +#ifndef QT_NO_PRINTER +#include <qdebug.h> +#include "private/qpaintengine_alpha_p.h" + +#include "private/qpicture_p.h" +#include "private/qfont_p.h" +#include "QtGui/qpicture.h" + +QT_BEGIN_NAMESPACE + +QAlphaPaintEngine::QAlphaPaintEngine(QAlphaPaintEnginePrivate &data, PaintEngineFeatures devcaps) + : QPaintEngine(data, devcaps) +{ + +} + +QAlphaPaintEngine::~QAlphaPaintEngine() +{ + +} + +bool QAlphaPaintEngine::begin(QPaintDevice *pdev) +{ + Q_D(QAlphaPaintEngine); + + d->m_continueCall = true; + if (d->m_pass != 0) { + return true; + } + + d->m_savedcaps = gccaps; + d->m_pdev = pdev; + + d->m_alphaPen = false; + d->m_alphaBrush = false; + d->m_alphaOpacity = false; + d->m_hasalpha = false; + d->m_advancedPen = false; + d->m_advancedBrush = false; + d->m_complexTransform = false; + d->m_emulateProjectiveTransforms = false; + + // clear alpha region + d->m_alphargn = QRegion(); + d->m_cliprgn = QRegion(); + d->m_pen = QPen(); + d->m_transform = QTransform(); + + flushAndInit(); + + return true; +} + +bool QAlphaPaintEngine::end() +{ + Q_D(QAlphaPaintEngine); + + d->m_continueCall = true; + if (d->m_pass != 0) { + return true; + } + + flushAndInit(false); + return true; +} + +void QAlphaPaintEngine::updateState(const QPaintEngineState &state) +{ + Q_D(QAlphaPaintEngine); + + DirtyFlags flags = state.state(); + if (flags & QPaintEngine::DirtyTransform) { + d->m_transform = state.transform(); + d->m_complexTransform = (d->m_transform.type() > QTransform::TxScale); + d->m_emulateProjectiveTransforms = !(d->m_savedcaps & QPaintEngine::PerspectiveTransform) + && !(d->m_savedcaps & QPaintEngine::AlphaBlend) + && (d->m_transform.type() >= QTransform::TxProject); + } + if (flags & QPaintEngine::DirtyPen) { + d->m_pen = state.pen(); + if (d->m_pen.style() == Qt::NoPen) { + d->m_advancedPen = false; + d->m_alphaPen = false; + } else { + d->m_advancedPen = (d->m_pen.brush().style() != Qt::SolidPattern); + d->m_alphaPen = !d->m_pen.brush().isOpaque(); + } + } + + if (d->m_pass != 0) { + d->m_continueCall = true; + return; + } + d->m_continueCall = false; + + if (flags & QPaintEngine::DirtyOpacity) { + d->m_alphaOpacity = (state.opacity() != 1.0f); + } + + if (flags & QPaintEngine::DirtyBrush) { + if (state.brush().style() == Qt::NoBrush) { + d->m_advancedBrush = false; + d->m_alphaBrush = false; + } else { + d->m_advancedBrush = (state.brush().style() != Qt::SolidPattern); + d->m_alphaBrush = !state.brush().isOpaque(); + } + } + + + d->m_hasalpha = d->m_alphaOpacity || d->m_alphaBrush || d->m_alphaPen; + + if (d->m_picengine) + d->m_picengine->updateState(state); +} + +void QAlphaPaintEngine::drawPath(const QPainterPath &path) +{ + Q_D(QAlphaPaintEngine); + + QRectF tr = d->addPenWidth(path); + + if (d->m_pass == 0) { + d->m_continueCall = false; + if (d->m_hasalpha || d->m_advancedPen || d->m_advancedBrush + || d->m_emulateProjectiveTransforms) + { + d->addAlphaRect(tr); + } + if (d->m_picengine) + d->m_picengine->drawPath(path); + } else { + d->m_continueCall = !d->fullyContained(tr); + } +} + +void QAlphaPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) +{ + Q_D(QAlphaPaintEngine); + + QPolygonF poly; + for (int i=0; i<pointCount; ++i) + poly.append(points[i]); + + QPainterPath path; + path.addPolygon(poly); + QRectF tr = d->addPenWidth(path); + + if (d->m_pass == 0) { + d->m_continueCall = false; + if (d->m_hasalpha || d->m_advancedPen || d->m_advancedBrush + || d->m_emulateProjectiveTransforms) + { + d->addAlphaRect(tr); + } + + if (d->m_picengine) + d->m_picengine->drawPolygon(points, pointCount, mode); + } else { + d->m_continueCall = !d->fullyContained(tr); + } +} + +void QAlphaPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ + Q_D(QAlphaPaintEngine); + + QRectF tr = d->m_transform.mapRect(r); + if (d->m_pass == 0) { + d->m_continueCall = false; + if (pm.hasAlpha() || d->m_alphaOpacity || d->m_complexTransform || pm.isQBitmap()) { + d->addAlphaRect(tr); + } + + if (d->m_picengine) + d->m_picengine->drawPixmap(r, pm, sr); + + } else { + d->m_continueCall = !d->fullyContained(tr); + } +} + +void QAlphaPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr) +{ + Q_D(QAlphaPaintEngine); + + QRectF tr = d->m_transform.mapRect(r); + if (d->m_pass == 0) { + d->m_continueCall = false; + if (image.hasAlphaChannel() || d->m_alphaOpacity || d->m_complexTransform) { + d->addAlphaRect(tr); + } + + if (d->m_picengine) + d->m_picengine->drawImage(r, image, sr); + + } else { + d->m_continueCall = !d->fullyContained(tr); + } +} + +void QAlphaPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) +{ + Q_D(QAlphaPaintEngine); + + QRectF tr(p.x(), p.y() - textItem.ascent(), textItem.width() + 5, textItem.ascent() + textItem.descent() + 5); + tr = d->m_transform.mapRect(tr); + + if (d->m_pass == 0) { + d->m_continueCall = false; + if (d->m_alphaPen || d->m_alphaOpacity || d->m_advancedPen) { + d->addAlphaRect(tr); + } + if (d->m_picengine) { + d->m_picengine->drawTextItem(p, textItem); + } + } else { + d->m_continueCall = !d->fullyContained(tr); + } +} + +void QAlphaPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) +{ + Q_D(QAlphaPaintEngine); + + QRectF brect = d->m_transform.mapRect(r); + + if (d->m_pass == 0) { + d->m_continueCall = false; + if (pixmap.hasAlpha() || d->m_alphaOpacity || d->m_complexTransform || pixmap.isQBitmap()) { + d->addAlphaRect(brect); + } + if (d->m_picengine) + d->m_picengine->drawTiledPixmap(r, pixmap, s); + } else { + d->m_continueCall = !d->fullyContained(brect); + } +} + +QRegion QAlphaPaintEngine::alphaClipping() const +{ + Q_D(const QAlphaPaintEngine); + return d->m_cliprgn; +} + +bool QAlphaPaintEngine::continueCall() const +{ + Q_D(const QAlphaPaintEngine); + return d->m_continueCall; +} + +void QAlphaPaintEngine::flushAndInit(bool init) +{ + Q_D(QAlphaPaintEngine); + Q_ASSERT(d->m_pass == 0); + + if (d->m_pic) { + d->m_picpainter->end(); + + // set clip region + d->m_alphargn = d->m_alphargn.intersected(QRect(0, 0, d->m_pdev->width(), d->m_pdev->height())); + + // just use the bounding rect if it's a complex region.. + QVector<QRect> rects = d->m_alphargn.rects(); + if (rects.size() > 10) { + QRect br = d->m_alphargn.boundingRect(); + d->m_alphargn = QRegion(br); + rects.clear(); + rects.append(br); + } + + d->m_cliprgn = d->m_alphargn; + + // now replay the QPicture + ++d->m_pass; // we are now doing pass #2 + + // reset states + gccaps = d->m_savedcaps; + + painter()->save(); + d->resetState(painter()); + + // make sure the output from QPicture is unscaled + QTransform mtx; + mtx.scale(1.0f / (qreal(d->m_pdev->logicalDpiX()) / qreal(qt_defaultDpiX())), + 1.0f / (qreal(d->m_pdev->logicalDpiY()) / qreal(qt_defaultDpiY()))); + painter()->setTransform(mtx); + painter()->drawPicture(0, 0, *d->m_pic); + + d->m_cliprgn = QRegion(); + d->resetState(painter()); + + // fill in the alpha images + for (int i=0; i<rects.size(); ++i) + d->drawAlphaImage(rects.at(i)); + + d->m_alphargn = QRegion(); + + painter()->restore(); + + --d->m_pass; // pass #2 finished + + cleanUp(); + } + + if (init) { + gccaps = PaintEngineFeatures(AllFeatures & ~QPaintEngine::ObjectBoundingModeGradients); + + d->m_pic = new QPicture(); + d->m_pic->d_ptr->in_memory_only = true; + d->m_picpainter = new QPainter(d->m_pic); + d->m_picengine = d->m_picpainter->paintEngine(); + + // When newPage() is called and the m_picpainter is recreated + // we have to copy the current state of the original printer + // painter back to the m_picpainter + d->m_picpainter->setPen(painter()->pen()); + d->m_picpainter->setBrush(painter()->brush()); + d->m_picpainter->setBrushOrigin(painter()->brushOrigin()); + d->m_picpainter->setFont(painter()->font()); + d->m_picpainter->setOpacity(painter()->opacity()); + d->m_picpainter->setTransform(painter()->combinedTransform()); + d->m_picengine->syncState(); + } +} + +void QAlphaPaintEngine::cleanUp() +{ + Q_D(QAlphaPaintEngine); + + delete d->m_picpainter; + delete d->m_pic; + + d->m_picpainter = 0; + d->m_pic = 0; + d->m_picengine = 0; +} + +QAlphaPaintEnginePrivate::QAlphaPaintEnginePrivate() + : m_pass(0), + m_pic(0), + m_picengine(0), + m_picpainter(0), + m_hasalpha(false), + m_alphaPen(false), + m_alphaBrush(false), + m_alphaOpacity(false), + m_advancedPen(false), + m_advancedBrush(false), + m_complexTransform(false) +{ + +} + +QAlphaPaintEnginePrivate::~QAlphaPaintEnginePrivate() +{ + delete m_picpainter; + delete m_pic; +} + +QRectF QAlphaPaintEnginePrivate::addPenWidth(const QPainterPath &path) +{ + QPainterPath tmp = path; + + if (m_pen.style() == Qt::NoPen) + return (path.controlPointRect() * m_transform).boundingRect(); + if (m_pen.isCosmetic()) + tmp = path * m_transform; + + QPainterPathStroker stroker; + if (m_pen.widthF() == 0.0f) + stroker.setWidth(1.0); + else + stroker.setWidth(m_pen.widthF()); + stroker.setJoinStyle(m_pen.joinStyle()); + stroker.setCapStyle(m_pen.capStyle()); + tmp = stroker.createStroke(tmp); + if (m_pen.isCosmetic()) + return tmp.controlPointRect(); + + return (tmp.controlPointRect() * m_transform).boundingRect(); +} + +QRect QAlphaPaintEnginePrivate::toRect(const QRectF &rect) const +{ + QRect r; + r.setLeft(int(rect.left())); + r.setTop(int(rect.top())); + r.setRight(int(rect.right() + 1)); + r.setBottom(int(rect.bottom() + 1)); + return r; +} + +void QAlphaPaintEnginePrivate::addAlphaRect(const QRectF &rect) +{ + m_alphargn |= toRect(rect); +} + +void QAlphaPaintEnginePrivate::drawAlphaImage(const QRectF &rect) +{ + Q_Q(QAlphaPaintEngine); + + qreal dpiX = qMax(m_pdev->logicalDpiX(), 300); + qreal dpiY = qMax(m_pdev->logicalDpiY(), 300); + qreal xscale = (dpiX / m_pdev->logicalDpiX()); + qreal yscale = (dpiY / m_pdev->logicalDpiY()); + + QTransform picscale; + picscale.scale(xscale, yscale); + + const int tileSize = 2048; + QSize size((int(rect.width() * xscale)), int(rect.height() * yscale)); + int divw = (size.width() / tileSize); + int divh = (size.height() / tileSize); + divw += 1; + divh += 1; + + int incx = int(rect.width() / divw); + int incy = int(rect.height() / divh); + + for (int y=0; y<divh; ++y) { + int ypos = int((incy * y) + rect.y()); + int height = int((y == (divh - 1)) ? (rect.height() - (incy * y)) : incy) + 1; + + for (int x=0; x<divw; ++x) { + int xpos = int((incx * x) + rect.x()); + int width = int((x == (divw - 1)) ? (rect.width() - (incx * x)) : incx) + 1; + + QSize imgsize((int)(width * xscale), (int)(height * yscale)); + QImage img(imgsize, QImage::Format_RGB32); + img.fill(0xffffffff); + + QPainter imgpainter(&img); + imgpainter.setTransform(picscale); + QPointF picpos(qreal(-xpos), qreal(-ypos)); + imgpainter.drawPicture(picpos, *m_pic); + imgpainter.end(); + + q->painter()->setTransform(QTransform()); + QRect r(xpos, ypos, width, height); + q->painter()->drawImage(r, img); + } + } +} + +bool QAlphaPaintEnginePrivate::fullyContained(const QRectF &rect) const +{ + QRegion r(toRect(rect)); + return (m_cliprgn.intersected(r) == r); +} + +void QAlphaPaintEnginePrivate::resetState(QPainter *p) +{ + p->setPen(QPen()); + p->setBrush(QBrush()); + p->setBrushOrigin(0,0); + p->setBackground(QBrush()); + p->setFont(QFont()); + p->setTransform(QTransform()); + // The view transform is already recorded and included in the + // picture we're about to replay. If we don't turn if off, + // the view matrix will be applied twice. + p->setViewTransformEnabled(false); + p->setClipRegion(QRegion(), Qt::NoClip); + p->setClipPath(QPainterPath(), Qt::NoClip); + p->setClipping(false); + p->setOpacity(1.0f); +} + + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qpaintengine_alpha_p.h b/src/printsupport/kernel/qpaintengine_alpha_p.h new file mode 100644 index 0000000000..5694e2a5bc --- /dev/null +++ b/src/printsupport/kernel/qpaintengine_alpha_p.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPAINTENGINE_ALPHA_P_H +#define QPAINTENGINE_ALPHA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QT_NO_PRINTER +#include "private/qpaintengine_p.h" + +QT_BEGIN_NAMESPACE + +class QAlphaPaintEnginePrivate; + +class QAlphaPaintEngine : public QPaintEngine +{ + Q_DECLARE_PRIVATE(QAlphaPaintEngine) +public: + ~QAlphaPaintEngine(); + + virtual bool begin(QPaintDevice *pdev); + virtual bool end(); + + virtual void updateState(const QPaintEngineState &state); + + virtual void drawPath(const QPainterPath &path); + + virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); + + virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + virtual void drawImage(const QRectF &r, const QImage &image, const QRectF &sr); + virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); + virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); + +protected: + QAlphaPaintEngine(QAlphaPaintEnginePrivate &data, PaintEngineFeatures devcaps = 0); + QRegion alphaClipping() const; + bool continueCall() const; + void flushAndInit(bool init = true); + void cleanUp(); +}; + +class QAlphaPaintEnginePrivate : public QPaintEnginePrivate +{ + Q_DECLARE_PUBLIC(QAlphaPaintEngine) +public: + QAlphaPaintEnginePrivate(); + ~QAlphaPaintEnginePrivate(); + + int m_pass; + QPicture *m_pic; + QPaintEngine *m_picengine; + QPainter *m_picpainter; + + QPaintEngine::PaintEngineFeatures m_savedcaps; + QPaintDevice *m_pdev; + + QRegion m_alphargn; + QRegion m_cliprgn; + + bool m_hasalpha; + bool m_alphaPen; + bool m_alphaBrush; + bool m_alphaOpacity; + bool m_advancedPen; + bool m_advancedBrush; + bool m_complexTransform; + bool m_emulateProjectiveTransforms; + bool m_continueCall; + + QTransform m_transform; + QPen m_pen; + + void addAlphaRect(const QRectF &rect); + QRectF addPenWidth(const QPainterPath &path); + void drawAlphaImage(const QRectF &rect); + QRect toRect(const QRectF &rect) const; + bool fullyContained(const QRectF &rect) const; + + void resetState(QPainter *p); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER + +#endif // QPAINTENGINE_ALPHA_P_H diff --git a/src/printsupport/kernel/qpaintengine_preview.cpp b/src/printsupport/kernel/qpaintengine_preview.cpp new file mode 100644 index 0000000000..3cf06f5770 --- /dev/null +++ b/src/printsupport/kernel/qpaintengine_preview.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qpaintengine_preview_p.h> +#include <private/qpainter_p.h> +#include <private/qpaintengine_p.h> +#include <private/qpicture_p.h> + +#include <QtPrintSupport/qprintengine.h> +#include <QtGui/qpainter.h> +#include <QtGui/qpicture.h> + +#ifndef QT_NO_PRINTPREVIEWWIDGET +QT_BEGIN_NAMESPACE + +class QPreviewPaintEnginePrivate : public QPaintEnginePrivate +{ + Q_DECLARE_PUBLIC(QPreviewPaintEngine) +public: + QPreviewPaintEnginePrivate() : state(QPrinter::Idle) {} + ~QPreviewPaintEnginePrivate() {} + + QList<const QPicture *> pages; + QPaintEngine *engine; + QPainter *painter; + QPrinter::PrinterState state; + + QPaintEngine *proxy_paint_engine; + QPrintEngine *proxy_print_engine; +}; + + +QPreviewPaintEngine::QPreviewPaintEngine() + : QPaintEngine(*(new QPreviewPaintEnginePrivate), PaintEngineFeatures(AllFeatures & ~ObjectBoundingModeGradients)) +{ + Q_D(QPreviewPaintEngine); + d->proxy_print_engine = 0; + d->proxy_paint_engine = 0; +} + +QPreviewPaintEngine::~QPreviewPaintEngine() +{ + Q_D(QPreviewPaintEngine); + + qDeleteAll(d->pages); +} + +bool QPreviewPaintEngine::begin(QPaintDevice *) +{ + Q_D(QPreviewPaintEngine); + + qDeleteAll(d->pages); + d->pages.clear(); + + QPicture *page = new QPicture; + page->d_func()->in_memory_only = true; + d->painter = new QPainter(page); + d->engine = d->painter->paintEngine(); + d->pages.append(page); + d->state = QPrinter::Active; + return true; +} + +bool QPreviewPaintEngine::end() +{ + Q_D(QPreviewPaintEngine); + + delete d->painter; + d->painter = 0; + d->engine = 0; + d->state = QPrinter::Idle; + return true; +} + +void QPreviewPaintEngine::updateState(const QPaintEngineState &state) +{ + Q_D(QPreviewPaintEngine); + d->engine->updateState(state); +} + +void QPreviewPaintEngine::drawPath(const QPainterPath &path) +{ + Q_D(QPreviewPaintEngine); + d->engine->drawPath(path); +} + +void QPreviewPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) +{ + Q_D(QPreviewPaintEngine); + d->engine->drawPolygon(points, pointCount, mode); +} + +void QPreviewPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) +{ + Q_D(QPreviewPaintEngine); + d->engine->drawTextItem(p, textItem); +} + +void QPreviewPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ + Q_D(QPreviewPaintEngine); + d->engine->drawPixmap(r, pm, sr); +} + +void QPreviewPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &p) +{ + Q_D(QPreviewPaintEngine); + d->engine->drawTiledPixmap(r, pm, p); +} + +bool QPreviewPaintEngine::newPage() +{ + Q_D(QPreviewPaintEngine); + + QPicture *page = new QPicture; + page->d_func()->in_memory_only = true; + QPainter *tmp_painter = new QPainter(page); + QPaintEngine *tmp_engine = tmp_painter->paintEngine(); + + // copy the painter state from the original painter + Q_ASSERT(painter()->d_func()->state && tmp_painter->d_func()->state); + *tmp_painter->d_func()->state = *painter()->d_func()->state; + + // composition modes aren't supported on a QPrinter and yields a + // warning, so ignore it for now + tmp_engine->setDirty(DirtyFlags(AllDirty & ~DirtyCompositionMode)); + tmp_engine->syncState(); + + delete d->painter; + d->painter = tmp_painter; + d->pages.append(page); + d->engine = tmp_engine; + return true; +} + +bool QPreviewPaintEngine::abort() +{ + Q_D(QPreviewPaintEngine); + end(); + qDeleteAll(d->pages); + d->state = QPrinter::Aborted; + + return true; +} + +QList<const QPicture *> QPreviewPaintEngine::pages() +{ + Q_D(QPreviewPaintEngine); + return d->pages; +} + +void QPreviewPaintEngine::setProxyEngines(QPrintEngine *printEngine, QPaintEngine *paintEngine) +{ + Q_D(QPreviewPaintEngine); + d->proxy_print_engine = printEngine; + d->proxy_paint_engine = paintEngine; +} + +void QPreviewPaintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) +{ + Q_D(QPreviewPaintEngine); + d->proxy_print_engine->setProperty(key, value); +} + +QVariant QPreviewPaintEngine::property(PrintEnginePropertyKey key) const +{ + Q_D(const QPreviewPaintEngine); + return d->proxy_print_engine->property(key); +} + +int QPreviewPaintEngine::metric(QPaintDevice::PaintDeviceMetric id) const +{ + Q_D(const QPreviewPaintEngine); + return d->proxy_print_engine->metric(id); +} + +QPrinter::PrinterState QPreviewPaintEngine::printerState() const +{ + Q_D(const QPreviewPaintEngine); + return d->state; +} + +QT_END_NAMESPACE + +#endif diff --git a/src/printsupport/kernel/qpaintengine_preview_p.h b/src/printsupport/kernel/qpaintengine_preview_p.h new file mode 100644 index 0000000000..c2e11313c2 --- /dev/null +++ b/src/printsupport/kernel/qpaintengine_preview_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPREVIEWPAINTENGINE_P_H +#define QPREVIEWPAINTENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of QPreviewPrinter and friends. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#include <QtGui/qpaintengine.h> +#include <QtPrintSupport/qprintengine.h> + +#ifndef QT_NO_PRINTPREVIEWWIDGET + +QT_BEGIN_NAMESPACE + +class QPreviewPaintEnginePrivate; + +class QPreviewPaintEngine : public QPaintEngine, public QPrintEngine +{ + Q_DECLARE_PRIVATE(QPreviewPaintEngine) +public: + QPreviewPaintEngine(); + ~QPreviewPaintEngine(); + + bool begin(QPaintDevice *dev); + bool end(); + + void updateState(const QPaintEngineState &state); + + void drawPath(const QPainterPath &path); + void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); + void drawTextItem(const QPointF &p, const QTextItem &textItem); + + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &p); + + QList<const QPicture *> pages(); + + QPaintEngine::Type type() const { return Picture; } + + void setProxyEngines(QPrintEngine *printEngine, QPaintEngine *paintEngine); + + void setProperty(PrintEnginePropertyKey key, const QVariant &value); + QVariant property(PrintEnginePropertyKey key) const; + + bool newPage(); + bool abort(); + + int metric(QPaintDevice::PaintDeviceMetric) const; + + QPrinter::PrinterState printerState() const; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTPREVIEWWIDGET + +#endif diff --git a/src/printsupport/kernel/qplatformprintersupport_qpa.cpp b/src/printsupport/kernel/qplatformprintersupport_qpa.cpp new file mode 100644 index 0000000000..3c11b3304c --- /dev/null +++ b/src/printsupport/kernel/qplatformprintersupport_qpa.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformprintersupport_qpa.h" + +#include <QtPrintSupport/qprinterinfo.h> + +#include <private/qprinterinfo_p.h> + +#ifndef QT_NO_PRINTER + +QT_BEGIN_NAMESPACE + +QPlatformPrinterSupport::QPlatformPrinterSupport() +{ +} + +QPlatformPrinterSupport::~QPlatformPrinterSupport() +{ +} + +QPrintEngine *QPlatformPrinterSupport::createNativePrintEngine(QPrinter::PrinterMode) +{ + return 0; +} + +QPaintEngine *QPlatformPrinterSupport::createPaintEngine(QPrintEngine *, QPrinter::PrinterMode) +{ + return 0; +} + +QList<QPrinter::PaperSize> QPlatformPrinterSupport::supportedPaperSizes(const QPrinterInfo &) const +{ + return QList<QPrinter::PaperSize>(); +} + +QList<QPrinterInfo> QPlatformPrinterSupport::availablePrinters() +{ + return QList<QPrinterInfo>(); +} + +QPrinterInfo QPlatformPrinterSupport::defaultPrinter() +{ + const QList<QPrinterInfo> printers = availablePrinters(); + foreach (const QPrinterInfo &printerInfo, printers) { + if (printerInfo.isDefault()) + return printerInfo; + } + return printers.isEmpty() ? QPrinterInfo() : printers.front(); +} + +QPrinterInfo QPlatformPrinterSupport::printerInfo(const QString &printerName, bool isDefault) +{ + QPrinterInfo pi = QPrinterInfo(printerName); + pi.d_func()->isDefault = isDefault; + return pi; +} + +void QPlatformPrinterSupport::setPrinterInfoDefault(QPrinterInfo *p, bool isDefault) +{ + p->d_func()->isDefault = isDefault; +} + +bool QPlatformPrinterSupport::printerInfoIsDefault(const QPrinterInfo &p) +{ + return p.d_func()->isDefault; +} + +int QPlatformPrinterSupport::printerInfoCupsPrinterIndex(const QPrinterInfo &p) +{ + int i = -1; +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)) || defined(Q_WS_QPA) +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + if (!p.isNull()) + return i = p.d_func()->cupsPrinterIndex; +#endif +#endif + Q_UNUSED(p) + return i; +} + +void QPlatformPrinterSupport::setPrinterInfoCupsPrinterIndex(QPrinterInfo *p, int index) +{ +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)) || defined(Q_WS_QPA) +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + p->d_func()->cupsPrinterIndex = index; +#endif +#endif + Q_UNUSED(p) + Q_UNUSED(index) +} + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qplatformprintersupport_qpa.h b/src/printsupport/kernel/qplatformprintersupport_qpa.h new file mode 100644 index 0000000000..800713c5bb --- /dev/null +++ b/src/printsupport/kernel/qplatformprintersupport_qpa.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMPRINTINGSUPPORT_H +#define QPLATFORMPRINTINGSUPPORT_H + +#include <QtPrintSupport/qprinter.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_PRINTER + +class QPrintEngine; + +class Q_PRINTSUPPORT_EXPORT QPlatformPrinterSupport +{ +public: + QPlatformPrinterSupport(); + virtual ~QPlatformPrinterSupport(); + + virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); + virtual QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode); + virtual QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const; + + virtual QList<QPrinterInfo> availablePrinters(); + virtual QPrinterInfo defaultPrinter(); + +protected: + static QPrinterInfo printerInfo(const QString &printerName, bool isDefault = false); + static void setPrinterInfoDefault(QPrinterInfo *p, bool isDefault); + static bool printerInfoIsDefault(const QPrinterInfo &p); + static int printerInfoCupsPrinterIndex(const QPrinterInfo &p); + static void setPrinterInfoCupsPrinterIndex(QPrinterInfo *p, int index); +}; + +#endif // QT_NO_PRINTER + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMPRINTINGSUPPORT_H diff --git a/src/printsupport/kernel/qplatformprintplugin.cpp b/src/printsupport/kernel/qplatformprintplugin.cpp new file mode 100644 index 0000000000..8b3c75127e --- /dev/null +++ b/src/printsupport/kernel/qplatformprintplugin.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformprintplugin_qpa.h" +#include "private/qfactoryloader_p.h" + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QPlatformPrinterSupportFactoryInterface_iid, QLatin1String("/printsupport"), Qt::CaseInsensitive)) +#endif + +QPlatformPrinterSupportPlugin::QPlatformPrinterSupportPlugin(QObject *parent) + : QObject(parent) +{ +} + +QPlatformPrinterSupportPlugin::~QPlatformPrinterSupportPlugin() +{ +} + +QPlatformPrinterSupport *QPlatformPrinterSupportPlugin::get() +{ + QStringList k = loader()->keys(); + if (k.isEmpty()) + return 0; + QPlatformPrinterSupportPlugin *plugin = qobject_cast<QPlatformPrinterSupportPlugin *>(loader()->instance(k.first())); + if (!plugin) + return 0; + return plugin->create(k.first()); +} + +QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qplatformprintplugin_qpa.h b/src/printsupport/kernel/qplatformprintplugin_qpa.h new file mode 100644 index 0000000000..831a0546b0 --- /dev/null +++ b/src/printsupport/kernel/qplatformprintplugin_qpa.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMPRINTERSUPPORTPLUGIN_H +#define QPLATFORMPRINTERSUPPORTPLUGIN_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformPrinterSupport; + +struct QPlatformPrinterSupportFactoryInterface : public QFactoryInterface +{ + virtual QPlatformPrinterSupport *create(const QString &key) = 0; +}; + +#define QPlatformPrinterSupportFactoryInterface_iid "org.qt-project.QPlatformPrinterSupportFactoryInterface" + +Q_DECLARE_INTERFACE(QPlatformPrinterSupportFactoryInterface, QPlatformPrinterSupportFactoryInterface_iid) + +class Q_PRINTSUPPORT_EXPORT QPlatformPrinterSupportPlugin : public QObject, public QPlatformPrinterSupportFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QPlatformPrinterSupportFactoryInterface:QFactoryInterface) +public: + explicit QPlatformPrinterSupportPlugin(QObject *parent = 0); + ~QPlatformPrinterSupportPlugin(); + + virtual QStringList keys() const = 0; + virtual QPlatformPrinterSupport *create(const QString &key) = 0; + + static QPlatformPrinterSupport *get(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMPRINTERSUPPORTPLUGIN_H diff --git a/src/printsupport/kernel/qprintengine.h b/src/printsupport/kernel/qprintengine.h new file mode 100644 index 0000000000..782b6ef8bd --- /dev/null +++ b/src/printsupport/kernel/qprintengine.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINTENGINE_H +#define QPRINTENGINE_H + +#include <QtCore/qvariant.h> +#include <QtPrintSupport/qprinter.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_PRINTER + +class Q_PRINTSUPPORT_EXPORT QPrintEngine +{ +public: + virtual ~QPrintEngine() {} + enum PrintEnginePropertyKey { + PPK_CollateCopies, + PPK_ColorMode, + PPK_Creator, + PPK_DocumentName, + PPK_FullPage, + PPK_NumberOfCopies, + PPK_Orientation, + PPK_OutputFileName, + PPK_PageOrder, + PPK_PageRect, + PPK_PageSize, + PPK_PaperRect, + PPK_PaperSource, + PPK_PrinterName, + PPK_PrinterProgram, + PPK_Resolution, + PPK_SelectionOption, + PPK_SupportedResolutions, + + PPK_WindowsPageSize, + PPK_FontEmbedding, + PPK_SuppressSystemPrintStatus, + + PPK_Duplex, + + PPK_PaperSources, + PPK_CustomPaperSize, + PPK_PageMargins, + PPK_CopyCount, + PPK_SupportsMultipleCopies, + PPK_PaperSize = PPK_PageSize, + + PPK_CustomBase = 0xff00 + }; + + virtual void setProperty(PrintEnginePropertyKey key, const QVariant &value) = 0; + virtual QVariant property(PrintEnginePropertyKey key) const = 0; + + virtual bool newPage() = 0; + virtual bool abort() = 0; + + virtual int metric(QPaintDevice::PaintDeviceMetric) const = 0; + + virtual QPrinter::PrinterState printerState() const = 0; + +#ifdef Q_WS_WIN + virtual HDC getPrinterDC() const { return 0; } + virtual void releasePrinterDC(HDC) const { } +#endif + +}; + +#endif // QT_NO_PRINTER + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPRINTENGINE_H diff --git a/src/printsupport/kernel/qprintengine_pdf.cpp b/src/printsupport/kernel/qprintengine_pdf.cpp new file mode 100644 index 0000000000..c8ce2cfa0f --- /dev/null +++ b/src/printsupport/kernel/qprintengine_pdf.cpp @@ -0,0 +1,666 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtPrintSupport/qprintengine.h> + +#include <qiodevice.h> +#include <qfile.h> +#include <qdebug.h> +#include <qbuffer.h> +#include "private/qcups_p.h" +#include "qprinterinfo.h" + +#ifndef QT_NO_PRINTER +#include <limits.h> +#include <math.h> + +#include "qprintengine_pdf_p.h" + +#ifdef Q_OS_UNIX +#include "private/qcore_unix_p.h" // overrides QT_OPEN +#endif + +#ifdef Q_OS_WIN +#include <io.h> // _close. +#endif + +QT_BEGIN_NAMESPACE + +//#define FONT_DUMP + +extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size); + +#define Q_MM(n) int((n * 720 + 127) / 254) +#define Q_IN(n) int(n * 72) + +static const char * const psToStr[QPrinter::NPageSize+1] = +{ + "A4", "B5", "Letter", "Legal", "Executive", + "A0", "A1", "A2", "A3", "A5", "A6", "A7", "A8", "A9", "B0", "B1", + "B10", "B2", "B3", "B4", "B6", "B7", "B8", "B9", "C5E", "Comm10E", + "DLE", "Folio", "Ledger", "Tabloid", 0 +}; + +QPdf::PaperSize QPdf::paperSize(QPrinter::PaperSize paperSize) +{ + QSizeF s = qt_paperSizeToQSizeF(paperSize); + PaperSize p = { Q_MM(s.width()), Q_MM(s.height()) }; + return p; +} + +const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize) +{ + return psToStr[paperSize]; +} + + +QPdfPrintEngine::QPdfPrintEngine(QPrinter::PrinterMode m) + : QPdfEngine(*new QPdfPrintEnginePrivate(m)) +{ + Q_D(QPdfPrintEngine); +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + if (QCUPSSupport::isAvailable()) { + QCUPSSupport cups; + const cups_dest_t* printers = cups.availablePrinters(); + int prnCount = cups.availablePrintersCount(); + + for (int i = 0; i < prnCount; ++i) { + if (printers[i].is_default) { + d->printerName = QString::fromLocal8Bit(printers[i].name); + break; + } + } + + } else +#endif + { + d->printerName = QString::fromLocal8Bit(qgetenv("PRINTER")); + if (d->printerName.isEmpty()) + d->printerName = QString::fromLocal8Bit(qgetenv("LPDEST")); + if (d->printerName.isEmpty()) + d->printerName = QString::fromLocal8Bit(qgetenv("NPRINTER")); + if (d->printerName.isEmpty()) + d->printerName = QString::fromLocal8Bit(qgetenv("NGPRINTER")); + } + + state = QPrinter::Idle; +} + +QPdfPrintEngine::~QPdfPrintEngine() +{ +} + +bool QPdfPrintEngine::begin(QPaintDevice *pdev) +{ + Q_D(QPdfPrintEngine); + + if (!d->openPrintDevice()) { + state = QPrinter::Error; + return false; + } + state = QPrinter::Active; + + return QPdfEngine::begin(pdev); +} + +bool QPdfPrintEngine::end() +{ + Q_D(QPdfPrintEngine); + + QPdfEngine::end(); + + d->closePrintDevice(); + state = QPrinter::Idle; + + return true; +} + +bool QPdfPrintEngine::newPage() +{ + return QPdfEngine::newPage(); +} + +int QPdfPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const +{ + return QPdfEngine::metric(m); +} + +void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) +{ + Q_D(QPdfPrintEngine); + + switch (int(key)) { + case PPK_CollateCopies: + d->collate = value.toBool(); + break; + case PPK_ColorMode: + d->grayscale = (QPrinter::ColorMode(value.toInt()) == QPrinter::GrayScale); + break; + case PPK_Creator: + d->creator = value.toString(); + break; + case PPK_DocumentName: + d->title = value.toString(); + break; + case PPK_FullPage: + d->fullPage = value.toBool(); + break; + case PPK_CopyCount: // fallthrough + case PPK_NumberOfCopies: + d->copies = value.toInt(); + break; + case PPK_Orientation: + d->landscape = (QPrinter::Orientation(value.toInt()) == QPrinter::Landscape); + break; + case PPK_OutputFileName: + d->outputFileName = value.toString(); + break; + case PPK_PageOrder: + d->pageOrder = QPrinter::PageOrder(value.toInt()); + break; + case PPK_PaperSize: + d->printerPaperSize = QPrinter::PaperSize(value.toInt()); + d->updatePaperSize(); + break; + case PPK_PaperSource: + d->paperSource = QPrinter::PaperSource(value.toInt()); + break; + case PPK_PrinterName: + d->printerName = value.toString(); + break; + case PPK_PrinterProgram: + d->printProgram = value.toString(); + break; + case PPK_Resolution: + d->resolution = value.toInt(); + break; + case PPK_SelectionOption: + d->selectionOption = value.toString(); + break; + case PPK_FontEmbedding: + d->embedFonts = value.toBool(); + break; + case PPK_Duplex: + d->duplex = static_cast<QPrinter::DuplexMode> (value.toInt()); + break; + case PPK_CupsPageRect: + d->cupsPageRect = value.toRect(); + break; + case PPK_CupsPaperRect: + d->cupsPaperRect = value.toRect(); + break; + case PPK_CupsOptions: + d->cupsOptions = value.toStringList(); + break; + case PPK_CupsStringPageSize: + d->cupsStringPageSize = value.toString(); + break; + case PPK_CustomPaperSize: + d->printerPaperSize = QPrinter::Custom; + d->customPaperSize = value.toSizeF(); + d->updatePaperSize(); + break; + case PPK_PageMargins: + { + QList<QVariant> margins(value.toList()); + Q_ASSERT(margins.size() == 4); + d->leftMargin = margins.at(0).toReal(); + d->topMargin = margins.at(1).toReal(); + d->rightMargin = margins.at(2).toReal(); + d->bottomMargin = margins.at(3).toReal(); + break; + } + default: + break; + } +} + +QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const +{ + Q_D(const QPdfPrintEngine); + + QVariant ret; + switch (int(key)) { + case PPK_CollateCopies: + ret = d->collate; + break; + case PPK_ColorMode: + ret = d->grayscale ? QPrinter::GrayScale : QPrinter::Color; + break; + case PPK_Creator: + ret = d->creator; + break; + case PPK_DocumentName: + ret = d->title; + break; + case PPK_FullPage: + ret = d->fullPage; + break; + case PPK_CopyCount: + ret = d->copies; + break; + case PPK_SupportsMultipleCopies: +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + if (QCUPSSupport::isAvailable()) + ret = true; + else +#endif + ret = false; + break; + case PPK_NumberOfCopies: +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + if (QCUPSSupport::isAvailable()) + ret = 1; + else +#endif + ret = d->copies; + break; + case PPK_Orientation: + ret = d->landscape ? QPrinter::Landscape : QPrinter::Portrait; + break; + case PPK_OutputFileName: + ret = d->outputFileName; + break; + case PPK_PageOrder: + ret = d->pageOrder; + break; + case PPK_PaperSize: + ret = d->paperSize; + break; + case PPK_PaperSource: + ret = d->paperSource; + break; + case PPK_PrinterName: + ret = d->printerName; + break; + case PPK_PrinterProgram: + ret = d->printProgram; + break; + case PPK_Resolution: + ret = d->resolution; + break; + case PPK_SupportedResolutions: + ret = QList<QVariant>() << 72; + break; + case PPK_PaperRect: + ret = d->paperRect(); + break; + case PPK_PageRect: + ret = d->pageRect(); + break; + case PPK_SelectionOption: + ret = d->selectionOption; + break; + case PPK_FontEmbedding: + ret = d->embedFonts; + break; + case PPK_Duplex: + ret = d->duplex; + break; + case PPK_CupsPageRect: + ret = d->cupsPageRect; + break; + case PPK_CupsPaperRect: + ret = d->cupsPaperRect; + break; + case PPK_CupsOptions: + ret = d->cupsOptions; + break; + case PPK_CupsStringPageSize: + ret = d->cupsStringPageSize; + break; + case PPK_CustomPaperSize: + ret = d->customPaperSize; + break; + case PPK_PageMargins: + { + QList<QVariant> margins; + margins << d->leftMargin << d->topMargin + << d->rightMargin << d->bottomMargin; + ret = margins; + break; + } + default: + break; + } + return ret; +} + + +#ifndef QT_NO_LPR +static void closeAllOpenFds() +{ + // hack time... getting the maximum number of open + // files, if possible. if not we assume it's the + // larger of 256 and the fd we got + int i; +#if defined(_SC_OPEN_MAX) + i = (int)sysconf(_SC_OPEN_MAX); +#elif defined(_POSIX_OPEN_MAX) + i = (int)_POSIX_OPEN_MAX; +#elif defined(OPEN_MAX) + i = (int)OPEN_MAX; +#else + i = 256; +#endif + // leave stdin/out/err untouched + while(--i > 2) + QT_CLOSE(i); +} +#endif + +bool QPdfPrintEnginePrivate::openPrintDevice() +{ + if (outDevice) + return false; + + if (!outputFileName.isEmpty()) { + QFile *file = new QFile(outputFileName); + if (! file->open(QFile::WriteOnly|QFile::Truncate)) { + delete file; + return false; + } + outDevice = file; +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + } else if (QCUPSSupport::isAvailable()) { + QCUPSSupport cups; + QPair<int, QString> ret = cups.tempFd(); + if (ret.first < 0) { + qWarning("QPdfPrinter: Could not open temporary file to print"); + return false; + } + cupsTempFile = ret.second; + outDevice = new QFile(); + static_cast<QFile *>(outDevice)->open(ret.first, QIODevice::WriteOnly); +#endif +#ifndef QT_NO_LPR + } else { + QString pr; + if (!printerName.isEmpty()) + pr = printerName; + int fds[2]; + if (qt_safe_pipe(fds) != 0) { + qWarning("QPdfPrinter: Could not open pipe to print"); + return false; + } + + pid_t pid = fork(); + if (pid == 0) { // child process + // if possible, exit quickly, so the actual lp/lpr + // becomes a child of init, and ::waitpid() is + // guaranteed not to wait. + if (fork() > 0) { + closeAllOpenFds(); + + // try to replace this process with "true" - this prevents + // global destructors from being called (that could possibly + // do wrong things to the parent process) + (void)execlp("true", "true", (char *)0); + (void)execl("/bin/true", "true", (char *)0); + (void)execl("/usr/bin/true", "true", (char *)0); + ::_exit(0); + } + qt_safe_dup2(fds[0], 0, 0); + + closeAllOpenFds(); + + if (!printProgram.isEmpty()) { + if (!selectionOption.isEmpty()) + pr.prepend(selectionOption); + else + pr.prepend(QLatin1String("-P")); + (void)execlp(printProgram.toLocal8Bit().data(), printProgram.toLocal8Bit().data(), + pr.toLocal8Bit().data(), (char *)0); + } else { + // if no print program has been specified, be smart + // about the option string too. + QList<QByteArray> lprhack; + QList<QByteArray> lphack; + QByteArray media; + if (!pr.isEmpty() || !selectionOption.isEmpty()) { + if (!selectionOption.isEmpty()) { + QStringList list = selectionOption.split(QLatin1Char(' ')); + for (int i = 0; i < list.size(); ++i) + lprhack.append(list.at(i).toLocal8Bit()); + lphack = lprhack; + } else { + lprhack.append("-P"); + lphack.append("-d"); + } + lprhack.append(pr.toLocal8Bit()); + lphack.append(pr.toLocal8Bit()); + } + lphack.append("-s"); + + char ** lpargs = new char *[lphack.size()+6]; + char lp[] = "lp"; + lpargs[0] = lp; + int i; + for (i = 0; i < lphack.size(); ++i) + lpargs[i+1] = (char *)lphack.at(i).constData(); +#ifndef Q_OS_OSF + if (QPdf::paperSizeToString(printerPaperSize)) { + char dash_o[] = "-o"; + lpargs[++i] = dash_o; + lpargs[++i] = const_cast<char *>(QPdf::paperSizeToString(printerPaperSize)); + lpargs[++i] = dash_o; + media = "media="; + media += QPdf::paperSizeToString(printerPaperSize); + lpargs[++i] = media.data(); + } +#endif + lpargs[++i] = 0; + char **lprargs = new char *[lprhack.size()+2]; + char lpr[] = "lpr"; + lprargs[0] = lpr; + for (int i = 0; i < lprhack.size(); ++i) + lprargs[i+1] = (char *)lprhack[i].constData(); + lprargs[lprhack.size() + 1] = 0; + (void)execvp("lp", lpargs); + (void)execvp("lpr", lprargs); + (void)execv("/bin/lp", lpargs); + (void)execv("/bin/lpr", lprargs); + (void)execv("/usr/bin/lp", lpargs); + (void)execv("/usr/bin/lpr", lprargs); + + delete []lpargs; + delete []lprargs; + } + // if we couldn't exec anything, close the fd, + // wait for a second so the parent process (the + // child of the GUI process) has exited. then + // exit. + QT_CLOSE(0); + (void)::sleep(1); + ::_exit(0); + } + // parent process + QT_CLOSE(fds[0]); + fd = fds[1]; + (void)qt_safe_waitpid(pid, 0, 0); + + if (fd < 0) + return false; + + outDevice = new QFile(); + static_cast<QFile *>(outDevice)->open(fd, QIODevice::WriteOnly); +#endif + } + + return true; +} + +void QPdfPrintEnginePrivate::closePrintDevice() +{ + if (outDevice) { + outDevice->close(); + if (fd >= 0) + #if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 + ::_close(fd); + #else + ::close(fd); + #endif + fd = -1; + delete outDevice; + outDevice = 0; + } + +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + if (!cupsTempFile.isEmpty()) { + QString tempFile = cupsTempFile; + cupsTempFile.clear(); + QCUPSSupport cups; + + // Set up print options. + QByteArray prnName; + QList<QPair<QByteArray, QByteArray> > options; + QVector<cups_option_t> cupsOptStruct; + + if (!printerName.isEmpty()) { + prnName = printerName.toLocal8Bit(); + } else { + QPrinterInfo def = QPrinterInfo::defaultPrinter(); + if (def.isNull()) { + qWarning("Could not determine printer to print to"); + QFile::remove(tempFile); + return; + } + prnName = def.printerName().toLocal8Bit(); + } + + if (!cupsStringPageSize.isEmpty()) { + options.append(QPair<QByteArray, QByteArray>("media", cupsStringPageSize.toLocal8Bit())); + } + + if (copies > 1) { + options.append(QPair<QByteArray, QByteArray>("copies", QString::number(copies).toLocal8Bit())); + } + + if (collate) { + options.append(QPair<QByteArray, QByteArray>("Collate", "True")); + } + + if (duplex != QPrinter::DuplexNone) { + switch(duplex) { + case QPrinter::DuplexNone: break; + case QPrinter::DuplexAuto: + if (!landscape) + options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge")); + else + options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge")); + break; + case QPrinter::DuplexLongSide: + options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge")); + break; + case QPrinter::DuplexShortSide: + options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge")); + break; + } + } + + if (QCUPSSupport::cupsVersion() >= 10300 && landscape) { + options.append(QPair<QByteArray, QByteArray>("landscape", "")); + } + + QStringList::const_iterator it = cupsOptions.constBegin(); + while (it != cupsOptions.constEnd()) { + options.append(QPair<QByteArray, QByteArray>((*it).toLocal8Bit(), (*(it+1)).toLocal8Bit())); + it += 2; + } + + for (int c = 0; c < options.size(); ++c) { + cups_option_t opt; + opt.name = options[c].first.data(); + opt.value = options[c].second.data(); + cupsOptStruct.append(opt); + } + + // Print the file. + cups_option_t* optPtr = cupsOptStruct.size() ? &cupsOptStruct.first() : 0; + cups.printFile(prnName.constData(), tempFile.toLocal8Bit().constData(), + title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr); + + QFile::remove(tempFile); + } +#endif +} + + + +QPdfPrintEnginePrivate::QPdfPrintEnginePrivate(QPrinter::PrinterMode m) + : QPdfEnginePrivate(), + duplex(QPrinter::DuplexNone), + collate(false), + copies(1), + pageOrder(QPrinter::FirstPageFirst), + paperSource(QPrinter::Auto), + printerPaperSize(QPrinter::A4), + fd(-1) +{ + resolution = 72; + if (m == QPrinter::HighResolution) + resolution = 1200; + else if (m == QPrinter::ScreenResolution) + resolution = qt_defaultDpi(); +} + +QPdfPrintEnginePrivate::~QPdfPrintEnginePrivate() +{ +} + + +void QPdfPrintEnginePrivate::updatePaperSize() +{ + if (printerPaperSize == QPrinter::Custom) { + paperSize = customPaperSize; + } else if (!cupsPaperRect.isNull()) { + QRect r = cupsPaperRect; + paperSize = r.size(); + } else{ + QPdf::PaperSize s = QPdf::paperSize(printerPaperSize); + paperSize = QSize(s.width, s.height); + } +} + + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qprintengine_pdf_p.h b/src/printsupport/kernel/qprintengine_pdf_p.h new file mode 100644 index 0000000000..483cde9af9 --- /dev/null +++ b/src/printsupport/kernel/qprintengine_pdf_p.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINTENGINE_PDF_P_H +#define QPRINTENGINE_PDF_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "QtPrintSupport/qprintengine.h" + +#ifndef QT_NO_PRINTER +#include "QtCore/qmap.h" +#include "QtGui/qmatrix.h" +#include "QtCore/qstring.h" +#include "QtCore/qvector.h" +#include "QtGui/qpaintengine.h" +#include "QtGui/qpainterpath.h" +#include "QtCore/qdatastream.h" + +#include "private/qfontengine_p.h" +#include "private/qpdf_p.h" +#include "private/qpaintengine_p.h" +#include "qprintengine.h" + +QT_BEGIN_NAMESPACE + +class QImage; +class QDataStream; +class QPen; +class QPointF; +class QRegion; +class QFile; +class QPdfPrintEngine; + +#define PPK_CupsOptions QPrintEngine::PrintEnginePropertyKey(0xfe00) +#define PPK_CupsPageRect QPrintEngine::PrintEnginePropertyKey(0xfe01) +#define PPK_CupsPaperRect QPrintEngine::PrintEnginePropertyKey(0xfe02) +#define PPK_CupsStringPageSize QPrintEngine::PrintEnginePropertyKey(0xfe03) + +namespace QPdf { + + struct PaperSize { + int width, height; // in postscript points + }; + Q_PRINTSUPPORT_EXPORT PaperSize paperSize(QPrinter::PaperSize paperSize); + Q_PRINTSUPPORT_EXPORT const char *paperSizeToString(QPrinter::PaperSize paperSize); +} + +class QPdfPrintEnginePrivate; + +class QPdfPrintEngine : public QPdfEngine, public QPrintEngine +{ + Q_DECLARE_PRIVATE(QPdfPrintEngine) +public: + QPdfPrintEngine(QPrinter::PrinterMode m); + virtual ~QPdfPrintEngine(); + + // reimplementations QPaintEngine + bool begin(QPaintDevice *pdev); + bool end(); + // end reimplementations QPaintEngine + + // reimplementations QPrintEngine + bool abort() {return false;} + QPrinter::PrinterState printerState() const {return state;} + + bool newPage(); + int metric(QPaintDevice::PaintDeviceMetric) const; + void setProperty(PrintEnginePropertyKey key, const QVariant &value); + QVariant property(PrintEnginePropertyKey key) const; + // end reimplementations QPrintEngine + + QPrinter::PrinterState state; + +private: + Q_DISABLE_COPY(QPdfPrintEngine) +}; + +class QPdfPrintEnginePrivate : public QPdfEnginePrivate +{ + Q_DECLARE_PUBLIC(QPdfPrintEngine) +public: + QPdfPrintEnginePrivate(QPrinter::PrinterMode m); + ~QPdfPrintEnginePrivate(); + + bool openPrintDevice(); + void closePrintDevice(); + + void updatePaperSize(); + +private: + Q_DISABLE_COPY(QPdfPrintEnginePrivate) + + QString printerName; + QString printProgram; + QString selectionOption; + QStringList cupsOptions; + QString cupsStringPageSize; + + QPrinter::DuplexMode duplex; + bool collate; + int copies; + QPrinter::PageOrder pageOrder; + QPrinter::PaperSource paperSource; + + QPrinter::PaperSize printerPaperSize; + QRect cupsPaperRect; + QRect cupsPageRect; + QSizeF customPaperSize; // in postscript points + + int fd; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER + +#endif // QPRINTENGINE_PDF_P_H diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp new file mode 100644 index 0000000000..ae215945d3 --- /dev/null +++ b/src/printsupport/kernel/qprinter.cpp @@ -0,0 +1,2264 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qprinter_p.h" +#include "qprinter.h" +#include "qprintengine.h" +#include "qprinterinfo.h" +#include "qlist.h" +#include <qcoreapplication.h> +#include <qfileinfo.h> +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) +#include "private/qcups_p.h" +#endif + +#ifndef QT_NO_PRINTER + +#include "qplatformprintplugin_qpa.h" +#include <QtPrintSupport/QPlatformPrinterSupport> +#include <private/qpagedpaintdevice_p.h> + +#if defined (Q_WS_WIN) +#include <private/qprintengine_win_p.h> +#elif defined (Q_WS_MAC) +#include <private/qprintengine_mac_p.h> +#elif defined (QTOPIA_PRINTENGINE) +#include <private/qprintengine_qws_p.h> +#endif + +#if defined(Q_WS_X11) +#include <private/qt_x11_p.h> +#endif + +#ifndef QT_NO_PDF +#include "qprintengine_pdf_p.h" +#endif + +#include <qpicture.h> +#include <private/qpaintengine_preview_p.h> + +QT_BEGIN_NAMESPACE + +#define ABORT_IF_ACTIVE(location) \ + if (d->printEngine->printerState() == QPrinter::Active) { \ + qWarning("%s: Cannot be changed while printer is active", location); \ + return; \ + } + +// NB! This table needs to be in sync with QPrinter::PaperSize +static const float qt_paperSizes[][2] = { + {210, 297}, // A4 + {176, 250}, // B5 + {215.9f, 279.4f}, // Letter + {215.9f, 355.6f}, // Legal + {190.5f, 254}, // Executive + {841, 1189}, // A0 + {594, 841}, // A1 + {420, 594}, // A2 + {297, 420}, // A3 + {148, 210}, // A5 + {105, 148}, // A6 + {74, 105}, // A7 + {52, 74}, // A8 + {37, 52}, // A8 + {1000, 1414}, // B0 + {707, 1000}, // B1 + {31, 44}, // B10 + {500, 707}, // B2 + {353, 500}, // B3 + {250, 353}, // B4 + {125, 176}, // B6 + {88, 125}, // B7 + {62, 88}, // B8 + {33, 62}, // B9 + {163, 229}, // C5E + {105, 241}, // US Common + {110, 220}, // DLE + {210, 330}, // Folio + {431.8f, 279.4f}, // Ledger + {279.4f, 431.8f} // Tabloid +}; + +/// return the multiplier of converting from the unit value to postscript-points. +Q_PRINTSUPPORT_EXPORT double qt_multiplierForUnit(QPrinter::Unit unit, int resolution) +{ + switch(unit) { + case QPrinter::Millimeter: + return 2.83464566929; + case QPrinter::Point: + return 1.0; + case QPrinter::Inch: + return 72.0; + case QPrinter::Pica: + return 12; + case QPrinter::Didot: + return 1.065826771; + case QPrinter::Cicero: + return 12.789921252; + case QPrinter::DevicePixel: + return 72.0/resolution; + } + return 1.0; +} + +// not static: it's needed in qpagesetupdialog_unix.cpp +Q_PRINTSUPPORT_EXPORT QSizeF qt_printerPaperSize(QPrinter::Orientation orientation, + QPrinter::PaperSize paperSize, + QPrinter::Unit unit, + int resolution) +{ + int width_index = 0; + int height_index = 1; + if (orientation == QPrinter::Landscape) { + width_index = 1; + height_index = 0; + } + const qreal multiplier = qt_multiplierForUnit(unit, resolution); + return QSizeF((qt_paperSizes[paperSize][width_index] * 72 / 25.4) / multiplier, + (qt_paperSizes[paperSize][height_index] * 72 / 25.4) / multiplier); +} + +void QPrinterPrivate::createDefaultEngines() +{ + QPrinter::OutputFormat realOutputFormat = outputFormat; +#if defined (Q_OS_UNIX) && ! defined (Q_WS_MAC) + if(outputFormat == QPrinter::NativeFormat) { + realOutputFormat = QPrinter::PdfFormat; + } +#endif + + switch (realOutputFormat) { + case QPrinter::NativeFormat: { +#if defined (Q_WS_QPA) + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (ps) { + printEngine = ps->createNativePrintEngine(printerMode); + paintEngine = ps->createPaintEngine(printEngine, printerMode); + } else { + QPdfPrintEngine *pdfEngine = new QPdfPrintEngine(printerMode); + paintEngine = pdfEngine; + printEngine = pdfEngine; + } +#elif defined (Q_WS_WIN) + QWin32PrintEngine *winEngine = new QWin32PrintEngine(printerMode); + paintEngine = winEngine; + printEngine = winEngine; +#elif defined (Q_WS_MAC) + QMacPrintEngine *macEngine = new QMacPrintEngine(printerMode); + paintEngine = macEngine; + printEngine = macEngine; +#elif defined (Q_OS_UNIX) + Q_ASSERT(false); +#endif + } + break; + case QPrinter::PdfFormat: { + QPdfPrintEngine *pdfEngine = new QPdfPrintEngine(printerMode); + paintEngine = pdfEngine; + printEngine = pdfEngine; + } + break; + } + use_default_engine = true; + had_default_engines = true; +} + +#ifndef QT_NO_PRINTPREVIEWWIDGET +QList<const QPicture *> QPrinterPrivate::previewPages() const +{ + if (previewEngine) + return previewEngine->pages(); + return QList<const QPicture *>(); +} + +void QPrinterPrivate::setPreviewMode(bool enable) +{ + Q_Q(QPrinter); + if (enable) { + if (!previewEngine) + previewEngine = new QPreviewPaintEngine; + had_default_engines = use_default_engine; + use_default_engine = false; + realPrintEngine = printEngine; + realPaintEngine = paintEngine; + q->setEngines(previewEngine, previewEngine); + previewEngine->setProxyEngines(realPrintEngine, realPaintEngine); + } else { + q->setEngines(realPrintEngine, realPaintEngine); + use_default_engine = had_default_engines; + } +} +#endif // QT_NO_PRINTPREVIEWWIDGET + +void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey key) +{ + for (int c = 0; c < manualSetList.size(); ++c) { + if (manualSetList[c] == key) return; + } + manualSetList.append(key); +} + + +/*! + \class QPrinter + \reentrant + + \brief The QPrinter class is a paint device that paints on a printer. + + \ingroup printing + + + This device represents a series of pages of printed output, and is + used in almost exactly the same way as other paint devices such as + QWidget and QPixmap. + A set of additional functions are provided to manage device-specific + features, such as orientation and resolution, and to step through + the pages in a document as it is generated. + + When printing directly to a printer on Windows or Mac OS X, QPrinter uses + the built-in printer drivers. On X11, QPrinter uses the + \l{Common Unix Printing System (CUPS)} or the standard Unix \l lpr utility + to send PDF output to the printer. As an alternative, + the printProgram() function can be used to specify the command or utility + to use instead of the system default. + + Note that setting parameters like paper size and resolution on an + invalid printer is undefined. You can use QPrinter::isValid() to + verify this before changing any parameters. + + QPrinter supports a number of parameters, most of which can be + changed by the end user through a \l{QPrintDialog}{print dialog}. In + general, QPrinter passes these functions onto the underlying QPrintEngine. + + The most important parameters are: + \list + \i setOrientation() tells QPrinter which page orientation to use. + \i setPaperSize() tells QPrinter what paper size to expect from the + printer. + \i setResolution() tells QPrinter what resolution you wish the + printer to provide, in dots per inch (DPI). + \i setFullPage() tells QPrinter whether you want to deal with the + full page or just with the part the printer can draw on. + \i setCopyCount() tells QPrinter how many copies of the document + it should print. + \endlist + + Many of these functions can only be called before the actual printing + begins (i.e., before QPainter::begin() is called). This usually makes + sense because, for example, it's not possible to change the number of + copies when you are halfway through printing. There are also some + settings that the user sets (through the printer dialog) and that + applications are expected to obey. See QAbstractPrintDialog's + documentation for more details. + + When QPainter::begin() is called, the QPrinter it operates on is prepared for + a new page, enabling the QPainter to be used immediately to paint the first + page in a document. Once the first page has been painted, newPage() can be + called to request a new blank page to paint on, or QPainter::end() can be + called to finish printing. The second page and all following pages are + prepared using a call to newPage() before they are painted. + + The first page in a document does not need to be preceded by a call to + newPage(). You only need to calling newPage() after QPainter::begin() if you + need to insert a blank page at the beginning of a printed document. + Similarly, calling newPage() after the last page in a document is painted will + result in a trailing blank page appended to the end of the printed document. + + If you want to abort the print job, abort() will try its best to + stop printing. It may cancel the entire job or just part of it. + + Since QPrinter can print to any QPrintEngine subclass, it is possible to + extend printing support to cover new types of printing subsystem by + subclassing QPrintEngine and reimplementing its interface. + + \sa QPrintDialog, {Printing with Qt} +*/ + +/*! + \enum QPrinter::PrinterState + + \value Idle + \value Active + \value Aborted + \value Error +*/ + +/*! + \enum QPrinter::PrinterMode + + This enum describes the mode the printer should work in. It + basically presets a certain resolution and working mode. + + \value ScreenResolution Sets the resolution of the print device to + the screen resolution. This has the big advantage that the results + obtained when painting on the printer will match more or less + exactly the visible output on the screen. It is the easiest to + use, as font metrics on the screen and on the printer are the + same. This is the default value. ScreenResolution will produce a + lower quality output than HighResolution and should only be used + for drafts. + + \value PrinterResolution This value is deprecated. Is is + equivalent to ScreenResolution on Unix and HighResolution on + Windows and Mac. Due do the difference between ScreenResolution + and HighResolution, use of this value may lead to non-portable + printer code. + + \value HighResolution On Windows, sets the printer resolution to that + defined for the printer in use. For PDF printing, sets the + resolution of the PDF driver to 1200 dpi. + + \note When rendering text on a QPrinter device, it is important + to realize that the size of text, when specified in points, is + independent of the resolution specified for the device itself. + Therefore, it may be useful to specify the font size in pixels + when combining text with graphics to ensure that their relative + sizes are what you expect. +*/ + +/*! + \enum QPrinter::Orientation + + This enum type (not to be confused with \c Orientation) is used + to specify each page's orientation. + + \value Portrait the page's height is greater than its width. + + \value Landscape the page's width is greater than its height. + + This type interacts with \l QPrinter::PaperSize and + QPrinter::setFullPage() to determine the final size of the page + available to the application. +*/ + + +/*! + \enum QPrinter::PrintRange + + Used to specify the print range selection option. + + \value AllPages All pages should be printed. + \value Selection Only the selection should be printed. + \value PageRange The specified page range should be printed. + \value CurrentPage Only the current page should be printed. + + \sa QAbstractPrintDialog::PrintRange +*/ + +/*! + \enum QPrinter::PrinterOption + \compat + + Use QAbstractPrintDialog::PrintDialogOption instead. + + \value PrintToFile + \value PrintSelection + \value PrintPageRange +*/ + +/*! + \enum QPrinter::PaperSize + \since 4.4 + + This enum type specifies what paper size QPrinter should use. + QPrinter does not check that the paper size is available; it just + uses this information, together with QPrinter::Orientation and + QPrinter::setFullPage(), to determine the printable area. + + The defined sizes (with setFullPage(true)) are: + + \value A0 841 x 1189 mm + \value A1 594 x 841 mm + \value A2 420 x 594 mm + \value A3 297 x 420 mm + \value A4 210 x 297 mm, 8.26 x 11.69 inches + \value A5 148 x 210 mm + \value A6 105 x 148 mm + \value A7 74 x 105 mm + \value A8 52 x 74 mm + \value A9 37 x 52 mm + \value B0 1000 x 1414 mm + \value B1 707 x 1000 mm + \value B2 500 x 707 mm + \value B3 353 x 500 mm + \value B4 250 x 353 mm + \value B5 176 x 250 mm, 6.93 x 9.84 inches + \value B6 125 x 176 mm + \value B7 88 x 125 mm + \value B8 62 x 88 mm + \value B9 33 x 62 mm + \value B10 31 x 44 mm + \value C5E 163 x 229 mm + \value Comm10E 105 x 241 mm, U.S. Common 10 Envelope + \value DLE 110 x 220 mm + \value Executive 7.5 x 10 inches, 190.5 x 254 mm + \value Folio 210 x 330 mm + \value Ledger 431.8 x 279.4 mm + \value Legal 8.5 x 14 inches, 215.9 x 355.6 mm + \value Letter 8.5 x 11 inches, 215.9 x 279.4 mm + \value Tabloid 279.4 x 431.8 mm + \value Custom Unknown, or a user defined size. + + With setFullPage(false) (the default), the metrics will be a bit + smaller; how much depends on the printer in use. + + \omitvalue NPageSize + \omitvalue NPaperSize +*/ + + +/*! + \enum QPrinter::PageOrder + + This enum type is used by QPrinter to tell the application program + how to print. + + \value FirstPageFirst the lowest-numbered page should be printed + first. + + \value LastPageFirst the highest-numbered page should be printed + first. +*/ + +/*! + \enum QPrinter::ColorMode + + This enum type is used to indicate whether QPrinter should print + in color or not. + + \value Color print in color if available, otherwise in grayscale. + + \value GrayScale print in grayscale, even on color printers. +*/ + +/*! + \enum QPrinter::PaperSource + + This enum type specifies what paper source QPrinter is to use. + QPrinter does not check that the paper source is available; it + just uses this information to try and set the paper source. + Whether it will set the paper source depends on whether the + printer has that particular source. + + \warning This is currently only implemented for Windows. + + \value Auto + \value Cassette + \value Envelope + \value EnvelopeManual + \value FormSource + \value LargeCapacity + \value LargeFormat + \value Lower + \value MaxPageSource + \value Middle + \value Manual + \value OnlyOne + \value Tractor + \value SmallFormat +*/ + +/*! + \enum QPrinter::Unit + \since 4.4 + + This enum type is used to specify the measurement unit for page and + paper sizes. + + \value Millimeter + \value Point + \value Inch + \value Pica + \value Didot + \value Cicero + \value DevicePixel + + Note the difference between Point and DevicePixel. The Point unit is + defined to be 1/72th of an inch, while the DevicePixel unit is + resolution dependant and is based on the actual pixels, or dots, on + the printer. +*/ + + +/* + \enum QPrinter::PrintRange + + This enum is used to specify which print range the application + should use to print. + + \value AllPages All the pages should be printed. + \value Selection Only the selection should be printed. + \value PageRange Print according to the from page and to page options. + \value CurrentPage Only the current page should be printed. + + \sa setPrintRange(), printRange() +*/ + +/* + \enum QPrinter::PrinterOption + + This enum describes various printer options that appear in the + printer setup dialog. It is used to enable and disable these + options in the setup dialog. + + \value PrintToFile Describes if print to file should be enabled. + \value PrintSelection Describes if printing selections should be enabled. + \value PrintPageRange Describes if printing page ranges (from, to) should + be enabled + \value PrintCurrentPage if Print Current Page option should be enabled + + \sa setOptionEnabled(), isOptionEnabled() +*/ + +/*! + Creates a new printer object with the given \a mode. +*/ +QPrinter::QPrinter(PrinterMode mode) + : QPagedPaintDevice(), + d_ptr(new QPrinterPrivate(this)) +{ + init(mode); + QPrinterInfo defPrn(QPrinterInfo::defaultPrinter()); + if (!defPrn.isNull()) { + setPrinterName(defPrn.printerName()); + } else if (QPrinterInfo::availablePrinters().isEmpty() + && d_ptr->paintEngine->type() != QPaintEngine::Windows + && d_ptr->paintEngine->type() != QPaintEngine::MacPrinter) { + setOutputFormat(QPrinter::PdfFormat); + } +} + +/*! + \since 4.4 + + Creates a new printer object with the given \a printer and \a mode. +*/ +QPrinter::QPrinter(const QPrinterInfo& printer, PrinterMode mode) + : QPagedPaintDevice(), + d_ptr(new QPrinterPrivate(this)) +{ + init(mode); + setPrinterName(printer.printerName()); +} + +void QPrinter::init(PrinterMode mode) +{ +#if !defined(Q_WS_X11) + if (!QCoreApplication::instance()) { +#else + if (!QCoreApplication::instance() || !X11) { +#endif + qFatal("QPrinter: Must construct a QApplication before a QPaintDevice"); + return; + } + Q_D(QPrinter); + + d->printerMode = mode; + d->outputFormat = QPrinter::NativeFormat; + d->createDefaultEngines(); + +#ifndef QT_NO_PRINTPREVIEWWIDGET + d->previewEngine = 0; +#endif + d->realPrintEngine = 0; + d->realPaintEngine = 0; + +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + if (QCUPSSupport::cupsVersion() >= 10200 && QCUPSSupport().currentPPD()) { + setOutputFormat(QPrinter::PdfFormat); + d->outputFormat = QPrinter::NativeFormat; + } +#endif +} + +/*! + This function is used by subclasses of QPrinter to specify custom + print and paint engines (\a printEngine and \a paintEngine, + respectively). + + QPrinter does not take ownership of the engines, so you need to + manage these engine instances yourself. + + Note that changing the engines will reset the printer state and + all its properties. + + \sa printEngine() paintEngine() setOutputFormat() + + \since 4.1 +*/ +void QPrinter::setEngines(QPrintEngine *printEngine, QPaintEngine *paintEngine) +{ + Q_D(QPrinter); + + if (d->use_default_engine) + delete d->printEngine; + + d->printEngine = printEngine; + d->paintEngine = paintEngine; + d->use_default_engine = false; +} + +/*! + Destroys the printer object and frees any allocated resources. If + the printer is destroyed while a print job is in progress this may + or may not affect the print job. +*/ +QPrinter::~QPrinter() +{ + Q_D(QPrinter); + if (d->use_default_engine) + delete d->printEngine; +#ifndef QT_NO_PRINTPREVIEWWIDGET + delete d->previewEngine; +#endif +} + +/*! + \enum QPrinter::OutputFormat + + The OutputFormat enum is used to describe the format QPrinter should + use for printing. + + \value NativeFormat QPrinter will print output using a method defined + by the platform it is running on. This mode is the default when printing + directly to a printer. + + \value PdfFormat QPrinter will generate its output as a searchable PDF file. + This mode is the default when printing to a file. + + \sa outputFormat(), setOutputFormat(), setOutputFileName() +*/ + +/*! + \since 4.1 + + Sets the output format for this printer to \a format. +*/ +void QPrinter::setOutputFormat(OutputFormat format) +{ + +#ifndef QT_NO_PDF + 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 (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 (def_engine) + delete oldPrintEngine; + + if (d->outputFormat == QPrinter::PdfFormat) + d->validPrinter = true; +#else + Q_UNUSED(format); +#endif +} + +/*! + \since 4.1 + + Returns the output format for this printer. +*/ +QPrinter::OutputFormat QPrinter::outputFormat() const +{ + Q_D(const QPrinter); + return d->outputFormat; +} + + + +/*! \internal +*/ +int QPrinter::devType() const +{ + return QInternal::Printer; +} + +/*! + Returns the printer name. This value is initially set to the name + of the default printer. + + \sa setPrinterName() +*/ +QString QPrinter::printerName() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_PrinterName).toString(); +} + +/*! + Sets the printer name to \a name. + + \sa printerName(), isValid() +*/ +void QPrinter::setPrinterName(const QString &name) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setPrinterName"); + +#if defined(Q_OS_UNIX) && !defined(QT_NO_CUPS) + if(d->use_default_engine && d->outputFormat == QPrinter::NativeFormat) { + setOutputFormat(QPrinter::PdfFormat); + d->outputFormat = QPrinter::NativeFormat; + } +#endif + + QList<QPrinterInfo> prnList = QPrinterInfo::availablePrinters(); + 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; + } + } + } + + d->printEngine->setProperty(QPrintEngine::PPK_PrinterName, name); + d->addToManualSetList(QPrintEngine::PPK_PrinterName); +} + + +/*! + \since 4.4 + + Returns true if the printer currently selected is a valid printer + in the system, or a pure PDF printer; otherwise returns false. + + To detect other failures check the output of QPainter::begin() or QPrinter::newPage(). + + \snippet doc/src/snippets/printing-qprinter/errors.cpp 0 + + \sa setPrinterName() +*/ +bool QPrinter::isValid() const +{ + Q_D(const QPrinter); +#if defined(Q_WS_X11) + if (!qApp || !X11) { + return false; + } +#endif + return d->validPrinter; +} + + +/*! + \fn bool QPrinter::outputToFile() const + + Returns true if the output should be written to a file, or false + if the output should be sent directly to the printer. The default + setting is false. + + \sa setOutputToFile(), setOutputFileName() +*/ + + +/*! + \fn void QPrinter::setOutputToFile(bool enable) + + Specifies whether the output should be written to a file or sent + directly to the printer. + + Will output to a file if \a enable is true, or will output + directly to the printer if \a enable is false. + + \sa outputToFile(), setOutputFileName() +*/ + + +/*! + \fn QString QPrinter::outputFileName() const + + Returns the name of the output file. By default, this is an empty string + (indicating that the printer shouldn't print to file). + + \sa QPrintEngine::PrintEnginePropertyKey + +*/ + +QString QPrinter::outputFileName() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_OutputFileName).toString(); +} + +/*! + Sets the name of the output file to \a fileName. + + Setting a null or empty name (0 or "") disables printing to a file. + Setting a non-empty name enables printing to a file. + + This can change the value of outputFormat(). + If the file name has the ".pdf" suffix PDF is generated. If the file name + has a suffix other than ".pdf", the output format used is the + one set with setOutputFormat(). + + QPrinter uses Qt's cross-platform PDF print engines + respectively. If you can produce this format natively, for example + Mac OS X can generate PDF's from its print engine, set the output format + back to NativeFormat. + + \sa outputFileName() setOutputToFile() setOutputFormat() +*/ + +void QPrinter::setOutputFileName(const QString &fileName) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setOutputFileName"); + + QFileInfo fi(fileName); + if (!fi.suffix().compare(QLatin1String("pdf"), Qt::CaseInsensitive)) + setOutputFormat(QPrinter::PdfFormat); + else if (fileName.isEmpty()) + setOutputFormat(QPrinter::NativeFormat); + + d->printEngine->setProperty(QPrintEngine::PPK_OutputFileName, fileName); + d->addToManualSetList(QPrintEngine::PPK_OutputFileName); +} + + +/*! + Returns the name of the program that sends the print output to the + printer. + + The default is to return an empty string; meaning that QPrinter will try to + be smart in a system-dependent way. On X11 only, you can set it to something + different to use a specific print program. On the other platforms, this + returns an empty string. + + \sa setPrintProgram(), setPrinterSelectionOption() +*/ +QString QPrinter::printProgram() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_PrinterProgram).toString(); +} + + +/*! + Sets the name of the program that should do the print job to \a + printProg. + + On X11, this function sets the program to call with the PDF + output. On other platforms, it has no effect. + + \sa printProgram() +*/ +void QPrinter::setPrintProgram(const QString &printProg) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setPrintProgram"); + d->printEngine->setProperty(QPrintEngine::PPK_PrinterProgram, printProg); + d->addToManualSetList(QPrintEngine::PPK_PrinterProgram); +} + + +/*! + Returns the document name. + + \sa setDocName(), QPrintEngine::PrintEnginePropertyKey +*/ +QString QPrinter::docName() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_DocumentName).toString(); +} + + +/*! + Sets the document name to \a name. + + On X11, the document name is for example used as the default + output filename in QPrintDialog. Note that the document name does + not affect the file name if the printer is printing to a file. + Use the setOutputFile() function for this. + + \sa docName(), QPrintEngine::PrintEnginePropertyKey +*/ +void QPrinter::setDocName(const QString &name) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setDocName"); + d->printEngine->setProperty(QPrintEngine::PPK_DocumentName, name); + d->addToManualSetList(QPrintEngine::PPK_DocumentName); +} + + +/*! + Returns the name of the application that created the document. + + \sa setCreator() +*/ +QString QPrinter::creator() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_Creator).toString(); +} + + +/*! + Sets the name of the application that created the document to \a + creator. + + This function is only applicable to the X11 version of Qt. If no + creator name is specified, the creator will be set to "Qt" + followed by some version number. + + \sa creator() +*/ +void QPrinter::setCreator(const QString &creator) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setCreator"); + d->printEngine->setProperty(QPrintEngine::PPK_Creator, creator); + d->addToManualSetList(QPrintEngine::PPK_Creator); +} + + +/*! + Returns the orientation setting. This is driver-dependent, but is usually + QPrinter::Portrait. + + \sa setOrientation() +*/ +QPrinter::Orientation QPrinter::orientation() const +{ + Q_D(const QPrinter); + return QPrinter::Orientation(d->printEngine->property(QPrintEngine::PPK_Orientation).toInt()); +} + + +/*! + Sets the print orientation to \a orientation. + + The orientation can be either QPrinter::Portrait or + QPrinter::Landscape. + + The printer driver reads this setting and prints using the + specified orientation. + + On Windows, this option can be changed while printing and will + take effect from the next call to newPage(). + + On Mac OS X, changing the orientation during a print job has no effect. + + \sa orientation() +*/ + +void QPrinter::setOrientation(Orientation orientation) +{ + Q_D(QPrinter); + d->printEngine->setProperty(QPrintEngine::PPK_Orientation, orientation); + d->addToManualSetList(QPrintEngine::PPK_Orientation); +} + + +/*! + \since 4.4 + Returns the printer paper size. The default value is driver-dependent. + + \sa setPaperSize() pageRect() paperRect() +*/ + +QPrinter::PaperSize QPrinter::paperSize() const +{ + Q_D(const QPrinter); + return QPrinter::PaperSize(d->printEngine->property(QPrintEngine::PPK_PaperSize).toInt()); +} + +/*! + \since 4.4 + + Sets the printer paper size to \a newPaperSize if that size is + supported. The result is undefined if \a newPaperSize is not + supported. + + The default paper size is driver-dependent. + + This function is useful mostly for setting a default value that + the user can override in the print dialog. + + \sa paperSize() PaperSize setFullPage() setResolution() pageRect() paperRect() +*/ +void QPrinter::setPaperSize(PaperSize newPaperSize) +{ + setPageSize(newPaperSize); +} + +/*! + \obsolete + + Returns the printer page size. The default value is driver-dependent. + + Use paperSize() instead. +*/ +QPrinter::PageSize QPrinter::pageSize() const +{ + return paperSize(); +} + + +/*! + \obsolete + + Sets the printer page size based on \a newPageSize. + + Use setPaperSize() instead. +*/ + +void QPrinter::setPageSize(PageSize newPageSize) +{ + QPagedPaintDevice::setPageSize(newPageSize); + + Q_D(QPrinter); + if (d->paintEngine->type() != QPaintEngine::Pdf) + ABORT_IF_ACTIVE("QPrinter::setPaperSize"); + if (newPageSize < 0 || newPageSize >= NPageSize) { + qWarning("QPrinter::setPaperSize: Illegal paper size %d", newPageSize); + return; + } + d->printEngine->setProperty(QPrintEngine::PPK_PaperSize, newPageSize); + d->addToManualSetList(QPrintEngine::PPK_PaperSize); + d->hasUserSetPageSize = true; +} + +/*! + \since 4.4 + + Sets the paper size based on \a paperSize in \a unit. + + \sa paperSize() +*/ + +void QPrinter::setPaperSize(const QSizeF &paperSize, QPrinter::Unit unit) +{ + Q_D(QPrinter); + if (d->paintEngine->type() != QPaintEngine::Pdf) + ABORT_IF_ACTIVE("QPrinter::setPaperSize"); + const qreal multiplier = qt_multiplierForUnit(unit, resolution()); + QSizeF size(paperSize.width() * multiplier * 25.4/72., paperSize.height() * multiplier * 25.4/72.); + setPageSizeMM(size); +} + +/*! + \reimp + */ +void QPrinter::setPageSizeMM(const QSizeF &size) +{ + Q_D(QPrinter); + + QPagedPaintDevice::setPageSizeMM(size); + + QSizeF s = size * 72./25.4; + d->printEngine->setProperty(QPrintEngine::PPK_CustomPaperSize, s); + d->addToManualSetList(QPrintEngine::PPK_CustomPaperSize); + d->hasUserSetPageSize = true; +} + +/*! + \since 4.4 + + Returns the paper size in \a unit. + + \sa setPaperSize() +*/ + +QSizeF QPrinter::paperSize(Unit unit) const +{ + Q_D(const QPrinter); + int res = resolution(); + const qreal multiplier = qt_multiplierForUnit(unit, res); + PaperSize paperType = paperSize(); + if (paperType == Custom) { + QSizeF size = d->printEngine->property(QPrintEngine::PPK_CustomPaperSize).toSizeF(); + return QSizeF(size.width() / multiplier, size.height() / multiplier); + } + else { + return qt_printerPaperSize(orientation(), paperType, unit, res); + } +} + +/*! + Sets the page order to \a pageOrder. + + The page order can be QPrinter::FirstPageFirst or + QPrinter::LastPageFirst. The application is responsible for + reading the page order and printing accordingly. + + This function is mostly useful for setting a default value that + the user can override in the print dialog. + + This function is only supported under X11. +*/ + +void QPrinter::setPageOrder(PageOrder pageOrder) +{ + d->pageOrderAscending = (pageOrder == FirstPageFirst); + + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setPageOrder"); + d->printEngine->setProperty(QPrintEngine::PPK_PageOrder, pageOrder); + d->addToManualSetList(QPrintEngine::PPK_PageOrder); +} + + +/*! + Returns the current page order. + + The default page order is \c FirstPageFirst. +*/ + +QPrinter::PageOrder QPrinter::pageOrder() const +{ + Q_D(const QPrinter); + return QPrinter::PageOrder(d->printEngine->property(QPrintEngine::PPK_PageOrder).toInt()); +} + + +/*! + Sets the printer's color mode to \a newColorMode, which can be + either \c Color or \c GrayScale. + + \sa colorMode() +*/ + +void QPrinter::setColorMode(ColorMode newColorMode) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setColorMode"); + d->printEngine->setProperty(QPrintEngine::PPK_ColorMode, newColorMode); + d->addToManualSetList(QPrintEngine::PPK_ColorMode); +} + + +/*! + Returns the current color mode. + + \sa setColorMode() +*/ +QPrinter::ColorMode QPrinter::colorMode() const +{ + Q_D(const QPrinter); + return QPrinter::ColorMode(d->printEngine->property(QPrintEngine::PPK_ColorMode).toInt()); +} + + +/*! + \obsolete + Returns the number of copies to be printed. The default value is 1. + + On Windows, Mac OS X and X11 systems that support CUPS, this will always + return 1 as these operating systems can internally handle the number + of copies. + + On X11, this value will return the number of times the application is + required to print in order to match the number specified in the printer setup + dialog. This has been done since some printer drivers are not capable of + buffering up the copies and in those cases the application must make an + explicit call to the print code for each copy. + + Use copyCount() in conjunction with supportsMultipleCopies() instead. + + \sa setNumCopies(), actualNumCopies() +*/ + +int QPrinter::numCopies() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_NumberOfCopies).toInt(); +} + + +/*! + \obsolete + \since 4.6 + + Returns the number of copies that will be printed. The default + value is 1. + + This function always returns the actual value specified in the print + dialog or using setNumCopies(). + + Use copyCount() instead. + + \sa setNumCopies(), numCopies() +*/ +int QPrinter::actualNumCopies() const +{ + return copyCount(); +} + + + +/*! + \obsolete + Sets the number of copies to be printed to \a numCopies. + + The printer driver reads this setting and prints the specified + number of copies. + + Use setCopyCount() instead. + + \sa numCopies() +*/ + +void QPrinter::setNumCopies(int numCopies) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setNumCopies"); + d->printEngine->setProperty(QPrintEngine::PPK_NumberOfCopies, numCopies); + d->addToManualSetList(QPrintEngine::PPK_NumberOfCopies); +} + +/*! + \since 4.7 + + Sets the number of copies to be printed to \a count. + + The printer driver reads this setting and prints the specified number of + copies. + + \sa copyCount(), supportsMultipleCopies() +*/ + +void QPrinter::setCopyCount(int count) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setCopyCount;"); + d->printEngine->setProperty(QPrintEngine::PPK_CopyCount, count); + d->addToManualSetList(QPrintEngine::PPK_CopyCount); +} + +/*! + \since 4.7 + + Returns the number of copies that will be printed. The default value is 1. + + \sa setCopyCount(), supportsMultipleCopies() +*/ + +int QPrinter::copyCount() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_CopyCount).toInt(); +} + +/*! + \since 4.7 + + Returns true if the printer supports printing multiple copies of the same + document in one job; otherwise false is returned. + + On most systems this function will return true. However, on X11 systems + that do not support CUPS, this function will return false. That means the + application has to handle the number of copies by printing the same + document the required number of times. + + \sa setCopyCount(), copyCount() +*/ + +bool QPrinter::supportsMultipleCopies() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_SupportsMultipleCopies).toBool(); +} + +/*! + \since 4.1 + + Returns true if collation is turned on when multiple copies is selected. + Returns false if it is turned off when multiple copies is selected. + When collating is turned off the printing of each individual page will be repeated + the numCopies() amount before the next page is started. With collating turned on + all pages are printed before the next copy of those pages is started. + + \sa setCollateCopies() +*/ +bool QPrinter::collateCopies() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_CollateCopies).toBool(); +} + + +/*! + \since 4.1 + + Sets the default value for collation checkbox when the print + dialog appears. If \a collate is true, it will enable + setCollateCopiesEnabled(). The default value is false. This value + will be changed by what the user presses in the print dialog. + + \sa collateCopies() +*/ +void QPrinter::setCollateCopies(bool collate) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setCollateCopies"); + d->printEngine->setProperty(QPrintEngine::PPK_CollateCopies, collate); + d->addToManualSetList(QPrintEngine::PPK_CollateCopies); +} + + + +/*! + If \a fp is true, enables support for painting over the entire page; + otherwise restricts painting to the printable area reported by the + device. + + By default, full page printing is disabled. In this case, the origin + of the QPrinter's coordinate system coincides with the top-left + corner of the printable area. + + If full page printing is enabled, the origin of the QPrinter's + coordinate system coincides with the top-left corner of the paper + itself. In this case, the + \l{QPaintDevice::PaintDeviceMetric}{device metrics} will report + the exact same dimensions as indicated by \l{PaperSize}. It may not + be possible to print on the entire physical page because of the + printer's margins, so the application must account for the margins + itself. + + \sa fullPage(), setPaperSize(), width(), height(), {Printing with Qt} +*/ + +void QPrinter::setFullPage(bool fp) +{ + Q_D(QPrinter); + d->printEngine->setProperty(QPrintEngine::PPK_FullPage, fp); + d->addToManualSetList(QPrintEngine::PPK_FullPage); +} + + +/*! + Returns true if the origin of the printer's coordinate system is + at the corner of the page and false if it is at the edge of the + printable area. + + See setFullPage() for details and caveats. + + \sa setFullPage() PaperSize +*/ + +bool QPrinter::fullPage() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_FullPage).toBool(); +} + + +/*! + Requests that the printer prints at \a dpi or as near to \a dpi as + possible. + + This setting affects the coordinate system as returned by, for + example QPainter::viewport(). + + This function must be called before QPainter::begin() to have an effect on + all platforms. + + \sa resolution() setPaperSize() +*/ + +void QPrinter::setResolution(int dpi) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setResolution"); + d->printEngine->setProperty(QPrintEngine::PPK_Resolution, dpi); + d->addToManualSetList(QPrintEngine::PPK_Resolution); +} + + +/*! + Returns the current assumed resolution of the printer, as set by + setResolution() or by the printer driver. + + \sa setResolution() +*/ + +int QPrinter::resolution() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_Resolution).toInt(); +} + +/*! + Sets the paper source setting to \a source. + + Windows only: This option can be changed while printing and will + take effect from the next call to newPage() + + \sa paperSource() +*/ + +void QPrinter::setPaperSource(PaperSource source) +{ + Q_D(QPrinter); + d->printEngine->setProperty(QPrintEngine::PPK_PaperSource, source); + d->addToManualSetList(QPrintEngine::PPK_PaperSource); +} + +/*! + Returns the printer's paper source. This is \c Manual or a printer + tray or paper cassette. +*/ +QPrinter::PaperSource QPrinter::paperSource() const +{ + Q_D(const QPrinter); + return QPrinter::PaperSource(d->printEngine->property(QPrintEngine::PPK_PaperSource).toInt()); +} + + +/*! + \since 4.1 + + Enabled or disables font embedding depending on \a enable. + + Currently this option is only supported on X11. + + \sa fontEmbeddingEnabled() +*/ +void QPrinter::setFontEmbeddingEnabled(bool enable) +{ + Q_D(QPrinter); + d->printEngine->setProperty(QPrintEngine::PPK_FontEmbedding, enable); + d->addToManualSetList(QPrintEngine::PPK_FontEmbedding); +} + +/*! + \since 4.1 + + Returns true if font embedding is enabled. + + Currently this option is only supported on X11. + + \sa setFontEmbeddingEnabled() +*/ +bool QPrinter::fontEmbeddingEnabled() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_FontEmbedding).toBool(); +} + +/*! + \enum QPrinter::DuplexMode + \since 4.4 + + This enum is used to indicate whether printing will occur on one or both sides + of each sheet of paper (simplex or duplex printing). + + \value DuplexNone Single sided (simplex) printing only. + \value DuplexAuto The printer's default setting is used to determine whether + duplex printing is used. + \value DuplexLongSide Both sides of each sheet of paper are used for printing. + The paper is turned over its longest edge before the second + side is printed + \value DuplexShortSide Both sides of each sheet of paper are used for printing. + The paper is turned over its shortest edge before the second + side is printed +*/ + +/*! + \since 4.2 + + Enables double sided printing if \a doubleSided is true; otherwise disables it. + + Currently this option is only supported on X11. +*/ +void QPrinter::setDoubleSidedPrinting(bool doubleSided) +{ + setDuplex(doubleSided ? DuplexAuto : DuplexNone); +} + + +/*! + \since 4.2 + + Returns true if double side printing is enabled. + + Currently this option is only supported on X11. +*/ +bool QPrinter::doubleSidedPrinting() const +{ + return duplex() != DuplexNone; +} + +/*! + \since 4.4 + + Enables double sided printing based on the \a duplex mode. + + Currently this option is only supported on X11. +*/ +void QPrinter::setDuplex(DuplexMode duplex) +{ + Q_D(QPrinter); + d->printEngine->setProperty(QPrintEngine::PPK_Duplex, duplex); + d->addToManualSetList(QPrintEngine::PPK_Duplex); +} + +/*! + \since 4.4 + + Returns the current duplex mode. + + Currently this option is only supported on X11. +*/ +QPrinter::DuplexMode QPrinter::duplex() const +{ + Q_D(const QPrinter); + return static_cast <DuplexMode> (d->printEngine->property(QPrintEngine::PPK_Duplex).toInt()); +} + +/*! + \since 4.4 + + Returns the page's rectangle in \a unit; this is usually smaller + than the paperRect() since the page normally has margins between + its borders and the paper. + + \sa paperSize() +*/ +QRectF QPrinter::pageRect(Unit unit) const +{ + Q_D(const QPrinter); + int res = resolution(); + const qreal multiplier = qt_multiplierForUnit(unit, res); + // the page rect is in device pixels + QRect devRect(d->printEngine->property(QPrintEngine::PPK_PageRect).toRect()); + if (unit == DevicePixel) + return devRect; + QRectF diRect(devRect.x()*72.0/res, + devRect.y()*72.0/res, + devRect.width()*72.0/res, + devRect.height()*72.0/res); + return QRectF(diRect.x()/multiplier, diRect.y()/multiplier, + diRect.width()/multiplier, diRect.height()/multiplier); +} + + +/*! + \since 4.4 + + Returns the paper's rectangle in \a unit; this is usually larger + than the pageRect(). + + \sa pageRect() +*/ +QRectF QPrinter::paperRect(Unit unit) const +{ + Q_D(const QPrinter); + int res = resolution(); + const qreal multiplier = qt_multiplierForUnit(unit, resolution()); + // the page rect is in device pixels + QRect devRect(d->printEngine->property(QPrintEngine::PPK_PaperRect).toRect()); + if (unit == DevicePixel) + return devRect; + QRectF diRect(devRect.x()*72.0/res, + devRect.y()*72.0/res, + devRect.width()*72.0/res, + devRect.height()*72.0/res); + return QRectF(diRect.x()/multiplier, diRect.y()/multiplier, + diRect.width()/multiplier, diRect.height()/multiplier); +} + +/*! + Returns the page's rectangle; this is usually smaller than the + paperRect() since the page normally has margins between its + borders and the paper. + + The unit of the returned rectangle is DevicePixel. + + \sa paperSize() +*/ +QRect QPrinter::pageRect() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_PageRect).toRect(); +} + +/*! + Returns the paper's rectangle; this is usually larger than the + pageRect(). + + The unit of the returned rectangle is DevicePixel. + + \sa pageRect() +*/ +QRect QPrinter::paperRect() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_PaperRect).toRect(); +} + + +/*! + \since 4.4 + + This function sets the \a left, \a top, \a right and \a bottom + page margins for this printer. The unit of the margins are + specified with the \a unit parameter. +*/ +void QPrinter::setPageMargins(qreal left, qreal top, qreal right, qreal bottom, QPrinter::Unit unit) +{ + const qreal multiplier = qt_multiplierForUnit(unit, resolution()) * 25.4/72.; + Margins m = { left*multiplier, right*multiplier, top*multiplier, bottom*multiplier }; + setMargins(m); +} + +/*! + reimp + */ +void QPrinter::setMargins(const Margins &m) +{ + Q_D(QPrinter); + + const qreal multiplier = 72./25.4; + QList<QVariant> margins; + margins << (m.left * multiplier) << (m.top * multiplier) + << (m.right * multiplier) << (m.bottom * multiplier); + d->printEngine->setProperty(QPrintEngine::PPK_PageMargins, margins); + d->addToManualSetList(QPrintEngine::PPK_PageMargins); + d->hasCustomPageMargins = true; +} + + +/*! + \since 4.4 + + Returns the page margins for this printer in \a left, \a top, \a + right, \a bottom. The unit of the returned margins are specified + with the \a unit parameter. +*/ +void QPrinter::getPageMargins(qreal *left, qreal *top, qreal *right, qreal *bottom, QPrinter::Unit unit) const +{ + Q_D(const QPrinter); + Q_ASSERT(left && top && right && bottom); + const qreal multiplier = qt_multiplierForUnit(unit, resolution()); + QList<QVariant> margins(d->printEngine->property(QPrintEngine::PPK_PageMargins).toList()); + *left = margins.at(0).toReal() / multiplier; + *top = margins.at(1).toReal() / multiplier; + *right = margins.at(2).toReal() / multiplier; + *bottom = margins.at(3).toReal() / multiplier; +} + +/*! + \internal + + Returns the metric for the given \a id. +*/ +int QPrinter::metric(PaintDeviceMetric id) const +{ + Q_D(const QPrinter); + return d->printEngine->metric(id); +} + +/*! + Returns the paint engine used by the printer. +*/ +QPaintEngine *QPrinter::paintEngine() const +{ + Q_D(const QPrinter); + return d->paintEngine; +} + +/*! + \since 4.1 + + Returns the print engine used by the printer. +*/ +QPrintEngine *QPrinter::printEngine() const +{ + Q_D(const QPrinter); + return d->printEngine; +} + +#if defined (Q_WS_WIN) +/*! + Sets the page size to be used by the printer under Windows to \a + pageSize. + + \warning This function is not portable so you may prefer to use + setPaperSize() instead. + + \sa winPageSize() +*/ +void QPrinter::setWinPageSize(int pageSize) +{ + Q_D(QPrinter); + ABORT_IF_ACTIVE("QPrinter::setWinPageSize"); + d->printEngine->setProperty(QPrintEngine::PPK_WindowsPageSize, pageSize); + d->addToManualSetList(QPrintEngine::PPK_WindowsPageSize); +} + +/*! + Returns the page size used by the printer under Windows. + + \warning This function is not portable so you may prefer to use + paperSize() instead. + + \sa setWinPageSize() +*/ +int QPrinter::winPageSize() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_WindowsPageSize).toInt(); +} +#endif // Q_WS_WIN + +/*! + Returns a list of the resolutions (a list of dots-per-inch + integers) that the printer says it supports. + + For X11 where all printing is directly to PDF, this + function will always return a one item list containing only the + PDF resolution, i.e., 72 (72 dpi -- but see PrinterMode). +*/ +QList<int> QPrinter::supportedResolutions() const +{ + Q_D(const QPrinter); + QList<QVariant> varlist + = d->printEngine->property(QPrintEngine::PPK_SupportedResolutions).toList(); + QList<int> intlist; + for (int i=0; i<varlist.size(); ++i) + intlist << varlist.at(i).toInt(); + return intlist; +} + +/*! + Tells the printer to eject the current page and to continue + printing on a new page. Returns true if this was successful; + otherwise returns false. + + Calling newPage() on an inactive QPrinter object will always + fail. +*/ +bool QPrinter::newPage() +{ + Q_D(QPrinter); + if (d->printEngine->printerState() != QPrinter::Active) + return false; + return d->printEngine->newPage(); +} + +/*! + Aborts the current print run. Returns true if the print run was + successfully aborted and printerState() will return QPrinter::Aborted; otherwise + returns false. + + It is not always possible to abort a print job. For example, + all the data has gone to the printer but the printer cannot or + will not cancel the job when asked to. +*/ +bool QPrinter::abort() +{ + Q_D(QPrinter); + return d->printEngine->abort(); +} + +/*! + Returns the current state of the printer. This may not always be + accurate (for example if the printer doesn't have the capability + of reporting its state to the operating system). +*/ +QPrinter::PrinterState QPrinter::printerState() const +{ + Q_D(const QPrinter); + return d->printEngine->printerState(); +} + + +/*! \fn void QPrinter::margins(uint *top, uint *left, uint *bottom, uint *right) const + + Sets *\a top, *\a left, *\a bottom, *\a right to be the top, + left, bottom, and right margins. + + This function has been superseded by paperRect() and pageRect(). + Use paperRect().top() - pageRect().top() for the top margin, + paperRect().left() - pageRect().left() for the left margin, + paperRect().bottom() - pageRect().bottom() for the bottom margin, + and papaerRect().right() - pageRect().right() for the right + margin. + + \oldcode + uint rightMargin; + uint bottomMargin; + printer->margins(0, 0, &bottomMargin, &rightMargin); + \newcode + int rightMargin = printer->paperRect().right() - printer->pageRect().right(); + int bottomMargin = printer->paperRect().bottom() - printer->pageRect().bottom(); + \endcode +*/ + +/*! \fn QSize QPrinter::margins() const + + \overload + + Returns a QSize containing the left margin and the top margin. + + This function has been superseded by paperRect() and pageRect(). + Use paperRect().left() - pageRect().left() for the left margin, + and paperRect().top() - pageRect().top() for the top margin. + + \oldcode + QSize margins = printer->margins(); + int leftMargin = margins.width(); + int topMargin = margins.height(); + \newcode + int leftMargin = printer->paperRect().left() - printer->pageRect().left(); + int topMargin = printer->paperRect().top() - printer->pageRect().top(); + \endcode +*/ + +/*! \fn bool QPrinter::aborted() + + Use printerState() == QPrinter::Aborted instead. +*/ + +#ifdef Q_WS_WIN +/*! + \internal +*/ +HDC QPrinter::getDC() const +{ + Q_D(const QPrinter); + return d->printEngine->getPrinterDC(); +} + +/*! + \internal +*/ +void QPrinter::releaseDC(HDC hdc) const +{ + Q_D(const QPrinter); + d->printEngine->releasePrinterDC(hdc); +} + +/*! + Returns the supported paper sizes for this printer. + + The values will be either a value that matches an entry in the + QPrinter::PaperSource enum or a driver spesific value. The driver + spesific values are greater than the constant DMBIN_USER declared + in wingdi.h. + + \warning This function is only available in windows. +*/ + +QList<QPrinter::PaperSource> QPrinter::supportedPaperSources() const +{ + Q_D(const QPrinter); + QVariant v = d->printEngine->property(QPrintEngine::PPK_PaperSources); + + QList<QVariant> variant_list = v.toList(); + QList<QPrinter::PaperSource> int_list; + for (int i=0; i<variant_list.size(); ++i) + int_list << (QPrinter::PaperSource) variant_list.at(i).toInt(); + + return int_list; +} + +#endif + +/*! + \fn QString QPrinter::printerSelectionOption() const + + Returns the printer options selection string. This is useful only + if the print command has been explicitly set. + + The default value (an empty string) implies that the printer should + be selected in a system-dependent manner. + + Any other value implies that the given value should be used. + + \warning This function is not available on Windows. + + \sa setPrinterSelectionOption() +*/ + +/*! + \fn void QPrinter::setPrinterSelectionOption(const QString &option) + + Sets the printer to use \a option to select the printer. \a option + is null by default (which implies that Qt should be smart enough + to guess correctly), but it can be set to other values to use a + specific printer selection option. + + If the printer selection option is changed while the printer is + active, the current print job may or may not be affected. + + \warning This function is not available on Windows. + + \sa printerSelectionOption() +*/ + +#ifndef Q_WS_WIN +QString QPrinter::printerSelectionOption() const +{ + Q_D(const QPrinter); + return d->printEngine->property(QPrintEngine::PPK_SelectionOption).toString(); +} + +void QPrinter::setPrinterSelectionOption(const QString &option) +{ + Q_D(QPrinter); + d->printEngine->setProperty(QPrintEngine::PPK_SelectionOption, option); + d->addToManualSetList(QPrintEngine::PPK_SelectionOption); +} +#endif + +/*! + \since 4.1 + \fn int QPrinter::fromPage() const + + Returns the number of the first page in a range of pages to be printed + (the "from page" setting). Pages in a document are numbered according to + the convention that the first page is page 1. + + By default, this function returns a special value of 0, meaning that + the "from page" setting is unset. + + \note If fromPage() and toPage() both return 0, this indicates that + \e{the whole document will be printed}. + + \sa setFromTo(), toPage() +*/ + +int QPrinter::fromPage() const +{ + return d->fromPage; +} + +/*! + \since 4.1 + + Returns the number of the last page in a range of pages to be printed + (the "to page" setting). Pages in a document are numbered according to + the convention that the first page is page 1. + + By default, this function returns a special value of 0, meaning that + the "to page" setting is unset. + + \note If fromPage() and toPage() both return 0, this indicates that + \e{the whole document will be printed}. + + The programmer is responsible for reading this setting and + printing accordingly. + + \sa setFromTo(), fromPage() +*/ + +int QPrinter::toPage() const +{ + return d->toPage; +} + +/*! + \since 4.1 + + Sets the range of pages to be printed to cover the pages with numbers + specified by \a from and \a to, where \a from corresponds to the first + page in the range and \a to corresponds to the last. + + \note Pages in a document are numbered according to the convention that + the first page is page 1. However, if \a from and \a to are both set to 0, + the \e{whole document will be printed}. + + This function is mostly used to set a default value that the user can + override in the print dialog when you call setup(). + + \sa fromPage(), toPage() +*/ + +void QPrinter::setFromTo(int from, int to) +{ + if (from > to) { + qWarning() << "QPrinter::setFromTo: 'from' must be less than or equal to 'to'"; + from = to; + } + d->fromPage = from; + d->toPage = to; +} + +/*! + \since 4.1 + + Sets the print range option in to be \a range. +*/ +void QPrinter::setPrintRange( PrintRange range ) +{ + d->printSelectionOnly = (range == Selection); + + Q_D(QPrinter); + d->printRange = range; +} + +/*! + \since 4.1 + + Returns the page range of the QPrinter. After the print setup + dialog has been opened, this function returns the value selected + by the user. + + \sa setPrintRange() +*/ +QPrinter::PrintRange QPrinter::printRange() const +{ + Q_D(const QPrinter); + return d->printRange; +} + + +/*! + \class QPrintEngine + \reentrant + + \ingroup printing + + \brief The QPrintEngine class defines an interface for how QPrinter + interacts with a given printing subsystem. + + The common case when creating your own print engine is to derive from both + QPaintEngine and QPrintEngine. Various properties of a print engine are + given with property() and set with setProperty(). + + \sa QPaintEngine +*/ + +/*! + \enum QPrintEngine::PrintEnginePropertyKey + + This enum is used to communicate properties between the print + engine and QPrinter. A property may or may not be supported by a + given print engine. + + \value PPK_CollateCopies A boolean value indicating whether the + printout should be collated or not. + + \value PPK_ColorMode Refers to QPrinter::ColorMode, either color or + monochrome. + + \value PPK_Creator A string describing the document's creator. + + \value PPK_Duplex A boolean value indicating whether both sides of + the printer paper should be used for the printout. + + \value PPK_DocumentName A string describing the document name in + the spooler. + + \value PPK_FontEmbedding A boolean value indicating whether data for + the document's fonts should be embedded in the data sent to the + printer. + + \value PPK_FullPage A boolean describing if the printer should be + full page or not. + + \value PPK_NumberOfCopies Obsolete. An integer specifying the number of + copies. Use PPK_CopyCount instead. + + \value PPK_Orientation Specifies a QPrinter::Orientation value. + + \value PPK_OutputFileName The output file name as a string. An + empty file name indicates that the printer should not print to a file. + + \value PPK_PageOrder Specifies a QPrinter::PageOrder value. + + \value PPK_PageRect A QRect specifying the page rectangle + + \value PPK_PageSize Obsolete. Use PPK_PaperSize instead. + + \value PPK_PaperRect A QRect specifying the paper rectangle. + + \value PPK_PaperSource Specifies a QPrinter::PaperSource value. + + \value PPK_PaperSources Specifies more than one QPrinter::PaperSource value. + + \value PPK_PaperSize Specifies a QPrinter::PaperSize value. + + \value PPK_PrinterName A string specifying the name of the printer. + + \value PPK_PrinterProgram A string specifying the name of the + printer program used for printing, + + \value PPK_Resolution An integer describing the dots per inch for + this printer. + + \value PPK_SelectionOption + + \value PPK_SupportedResolutions A list of integer QVariants + describing the set of supported resolutions that the printer has. + + \value PPK_SuppressSystemPrintStatus Suppress the built-in dialog for showing + printing progress. As of 4.1 this only has effect on Mac OS X where, by default, + a status dialog is shown. + + \value PPK_WindowsPageSize An integer specifying a DM_PAPER entry + on Windows. + + \value PPK_CustomPaperSize A QSizeF specifying a custom paper size + in the QPrinter::Point unit. + + \value PPK_PageMargins A QList<QVariant> containing the left, top, + right and bottom margin values. + + \value PPK_CopyCount An integer specifying the number of copies to print. + + \value PPK_SupportsMultipleCopies A boolean value indicating whether or not + the printer supports printing multiple copies in one job. + + \value PPK_CustomBase Basis for extension. +*/ + +/*! + \fn QPrintEngine::~QPrintEngine() + + Destroys the print engine. +*/ + +/*! + \fn void QPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) + + Sets the print engine's property specified by \a key to the given \a value. + + \sa property() +*/ + +/*! + \fn void QPrintEngine::property(PrintEnginePropertyKey key) const + + Returns the print engine's property specified by \a key. + + \sa setProperty() +*/ + +/*! + \fn bool QPrintEngine::newPage() + + Instructs the print engine to start a new page. Returns true if + the printer was able to create the new page; otherwise returns false. +*/ + +/*! + \fn bool QPrintEngine::abort() + + Instructs the print engine to abort the printing process. Returns + true if successful; otherwise returns false. +*/ + +/*! + \fn int QPrintEngine::metric(QPaintDevice::PaintDeviceMetric id) const + + Returns the metric for the given \a id. +*/ + +/*! + \fn QPrinter::PrinterState QPrintEngine::printerState() const + + Returns the current state of the printer being used by the print engine. +*/ + +/*! + \fn HDC QPrintEngine::getPrinterDC() const + \internal +*/ + +/*! + \fn void QPrintEngine::releasePrinterDC(HDC) const + \internal +*/ + +/* + Returns the dimensions for the given paper size, \a size, in millimeters. +*/ +QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size) +{ + if (size == QPrinter::Custom) return QSizeF(0, 0); + return QSizeF(qt_paperSizes[size][0], qt_paperSizes[size][1]); +} + +/* + Returns the PaperSize type that matches \a size, where \a size + is in millimeters. + + Because dimensions may not always be completely accurate (for + example when converting between units), a particular PaperSize + will be returned if it matches within -1/+1 millimeters. +*/ +QPrinter::PaperSize qSizeFTopaperSize(const QSizeF& size) +{ + for (int i = 0; i < static_cast<int>(QPrinter::NPageSize); ++i) { + if (qt_paperSizes[i][0] >= size.width() - 1 && + qt_paperSizes[i][0] <= size.width() + 1 && + qt_paperSizes[i][1] >= size.height() - 1 && + qt_paperSizes[i][1] <= size.height() + 1) { + return QPrinter::PaperSize(i); + } + } + + return QPrinter::Custom; +} + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qprinter.h b/src/printsupport/kernel/qprinter.h new file mode 100644 index 0000000000..7d04099a8f --- /dev/null +++ b/src/printsupport/kernel/qprinter.h @@ -0,0 +1,279 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINTER_H +#define QPRINTER_H + +#include <QtCore/qstring.h> +#include <QtCore/qscopedpointer.h> +#include <QtGui/qpagedpaintdevice.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_PRINTER + +#if defined(B0) +#undef B0 // Terminal hang-up. We assume that you do not want that. +#endif + +class QPrinterPrivate; +class QPaintEngine; +class QPrintEngine; +class QPrinterInfo; + +class Q_PRINTSUPPORT_EXPORT QPrinter : public QPagedPaintDevice +{ + Q_DECLARE_PRIVATE(QPrinter) +public: + enum PrinterMode { ScreenResolution, PrinterResolution, HighResolution }; + + explicit QPrinter(PrinterMode mode = ScreenResolution); + explicit QPrinter(const QPrinterInfo& printer, PrinterMode mode = ScreenResolution); + ~QPrinter(); + + int devType() const; + + enum Orientation { Portrait, Landscape }; + +#ifndef Q_QDOC + typedef PageSize PaperSize; +#else + enum PaperSize { A4, B5, Letter, Legal, Executive, + A0, A1, A2, A3, A5, A6, A7, A8, A9, B0, B1, + B10, B2, B3, B4, B6, B7, B8, B9, C5E, Comm10E, + DLE, Folio, Ledger, Tabloid, Custom, NPageSize = Custom, NPaperSize = Custom }; +#endif + + enum PageOrder { FirstPageFirst, + LastPageFirst }; + + enum ColorMode { GrayScale, + Color }; + + enum PaperSource { OnlyOne, + Lower, + Middle, + Manual, + Envelope, + EnvelopeManual, + Auto, + Tractor, + SmallFormat, + LargeFormat, + LargeCapacity, + Cassette, + FormSource, + MaxPageSource + }; + + enum PrinterState { Idle, + Active, + Aborted, + Error }; + + enum OutputFormat { NativeFormat, PdfFormat }; + + // Keep in sync with QAbstractPrintDialog::PrintRange + enum PrintRange { AllPages, Selection, PageRange, CurrentPage }; + + enum Unit { + Millimeter, + Point, + Inch, + Pica, + Didot, + Cicero, + DevicePixel + }; + + enum DuplexMode { + DuplexNone = 0, + DuplexAuto, + DuplexLongSide, + DuplexShortSide + }; + + void setOutputFormat(OutputFormat format); + OutputFormat outputFormat() const; + + void setPrinterName(const QString &); + QString printerName() const; + + bool isValid() const; + + void setOutputFileName(const QString &); + QString outputFileName()const; + + void setPrintProgram(const QString &); + QString printProgram() const; + + void setDocName(const QString &); + QString docName() const; + + void setCreator(const QString &); + QString creator() const; + + void setOrientation(Orientation); + Orientation orientation() const; + + void setPageSize(PageSize); + PageSize pageSize() const; + + void setPageSizeMM(const QSizeF &size); + + void setPaperSize(PaperSize); + PaperSize paperSize() const; + + void setPaperSize(const QSizeF &paperSize, Unit unit); + QSizeF paperSize(Unit unit) const; + + void setPageOrder(PageOrder); + PageOrder pageOrder() const; + + void setResolution(int); + int resolution() const; + + void setColorMode(ColorMode); + ColorMode colorMode() const; + + void setCollateCopies(bool collate); + bool collateCopies() const; + + void setFullPage(bool); + bool fullPage() const; + + void setNumCopies(int); + int numCopies() const; + + int actualNumCopies() const; + + void setCopyCount(int); + int copyCount() const; + bool supportsMultipleCopies() const; + + void setPaperSource(PaperSource); + PaperSource paperSource() const; + + void setDuplex(DuplexMode duplex); + DuplexMode duplex() const; + + QList<int> supportedResolutions() const; + +#ifdef Q_WS_WIN + QList<PaperSource> supportedPaperSources() const; +#endif + + void setFontEmbeddingEnabled(bool enable); + bool fontEmbeddingEnabled() const; + + void setDoubleSidedPrinting(bool enable); + bool doubleSidedPrinting() const; + +#ifdef Q_WS_WIN + void setWinPageSize(int winPageSize); + int winPageSize() const; +#endif + + QRect paperRect() const; + QRect pageRect() const; + QRectF paperRect(Unit) const; + QRectF pageRect(Unit) const; + +#if !defined(Q_WS_WIN) || defined(qdoc) + QString printerSelectionOption() const; + void setPrinterSelectionOption(const QString &); +#endif + + bool newPage(); + bool abort(); + + PrinterState printerState() const; + + QPaintEngine *paintEngine() const; + QPrintEngine *printEngine() const; + +#ifdef Q_WS_WIN + HDC getDC() const; + void releaseDC(HDC hdc) const; +#endif + + void setFromTo(int fromPage, int toPage); + int fromPage() const; + int toPage() const; + + void setPrintRange(PrintRange range); + PrintRange printRange() const; + + void setMargins(const Margins &m); + + void setPageMargins(qreal left, qreal top, qreal right, qreal bottom, Unit unit); + void getPageMargins(qreal *left, qreal *top, qreal *right, qreal *bottom, Unit unit) const; + +protected: + int metric(PaintDeviceMetric) const; + void setEngines(QPrintEngine *printEngine, QPaintEngine *paintEngine); + +private: + void init(PrinterMode mode); + + Q_DISABLE_COPY(QPrinter) + + QScopedPointer<QPrinterPrivate> d_ptr; + + friend class QPrintDialogPrivate; + friend class QAbstractPrintDialog; + friend class QAbstractPrintDialogPrivate; + friend class QPrintPreviewWidgetPrivate; + friend class QTextDocument; + friend class QPageSetupWidget; +}; + +#endif // QT_NO_PRINTER + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPRINTER_H diff --git a/src/printsupport/kernel/qprinter_p.h b/src/printsupport/kernel/qprinter_p.h new file mode 100644 index 0000000000..08877f08c5 --- /dev/null +++ b/src/printsupport/kernel/qprinter_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINTER_P_H +#define QPRINTER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include "QtCore/qglobal.h" + +#ifndef QT_NO_PRINTER + +#include "QtPrintSupport/qprinter.h" +#include "QtPrintSupport/qprintengine.h" +#include "QtCore/qpointer.h" + +#include <limits.h> + +QT_BEGIN_NAMESPACE + +class QPrintEngine; +class QPreviewPaintEngine; +class QPicture; + +class Q_PRINTSUPPORT_EXPORT QPrinterPrivate +{ + Q_DECLARE_PUBLIC(QPrinter) +public: + QPrinterPrivate(QPrinter *printer) + : printEngine(0) + , paintEngine(0) + , q_ptr(printer) + , printRange(QPrinter::AllPages) + , use_default_engine(true) + , validPrinter(false) + , hasCustomPageMargins(false) + , hasUserSetPageSize(false) + { + } + + ~QPrinterPrivate() { + + } + + void createDefaultEngines(); +#ifndef QT_NO_PRINTPREVIEWWIDGET + QList<const QPicture *> previewPages() const; + void setPreviewMode(bool); +#endif + + void addToManualSetList(QPrintEngine::PrintEnginePropertyKey key); + + QPrinter::PrinterMode printerMode; + QPrinter::OutputFormat outputFormat; + QPrintEngine *printEngine; + QPaintEngine *paintEngine; + + QPrintEngine *realPrintEngine; + QPaintEngine *realPaintEngine; +#ifndef QT_NO_PRINTPREVIEWWIDGET + QPreviewPaintEngine *previewEngine; +#endif + + QPrinter *q_ptr; + + QPrinter::PrintRange printRange; + + uint use_default_engine : 1; + uint had_default_engines : 1; + + uint validPrinter : 1; + uint hasCustomPageMargins : 1; + uint hasUserSetPageSize : 1; + + // Used to remember which properties have been manually set by the user. + QList<QPrintEngine::PrintEnginePropertyKey> manualSetList; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER + +#endif // QPRINTER_P_H diff --git a/src/printsupport/kernel/qprinterinfo.cpp b/src/printsupport/kernel/qprinterinfo.cpp new file mode 100644 index 0000000000..5be73e76b9 --- /dev/null +++ b/src/printsupport/kernel/qprinterinfo.cpp @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qprinterinfo.h" +#include "qprinterinfo_p.h" + +#ifndef QT_NO_PRINTER + +#include "qplatformprintplugin_qpa.h" +#include <QtPrintSupport/QPlatformPrinterSupport> + +QT_BEGIN_NAMESPACE + +QPrinterInfoPrivate QPrinterInfoPrivate::shared_null; + + +/*! + \class QPrinterInfo + + \brief The QPrinterInfo class gives access to information about + existing printers. + + \ingroup printing + + Use the static functions to generate a list of QPrinterInfo + objects. Each QPrinterInfo object in the list represents a single + printer and can be queried for name, supported paper sizes, and + whether or not it is the default printer. + + \since 4.4 +*/ + +/*! + \fn QList<QPrinterInfo> QPrinterInfo::availablePrinters() + + Returns a list of available printers on the system. +*/ + +/*! + \fn QPrinterInfo QPrinterInfo::defaultPrinter() + + Returns the default printer on the system. + + The return value should be checked using isNull() before being + used, in case there is no default printer. + + \sa isNull() +*/ + +/*! + Constructs an empty QPrinterInfo object. + + \sa isNull() +*/ +QPrinterInfo::QPrinterInfo() + : d_ptr(&QPrinterInfoPrivate::shared_null) +{ +} + +/*! + Constructs a copy of \a other. +*/ +QPrinterInfo::QPrinterInfo(const QPrinterInfo &other) + : d_ptr(new QPrinterInfoPrivate(*other.d_ptr)) +{ +} + +/*! + Constructs a QPrinterInfo object from \a printer. +*/ +QPrinterInfo::QPrinterInfo(const QPrinter &printer) + : d_ptr(&QPrinterInfoPrivate::shared_null) +{ + foreach (const QPrinterInfo &printerInfo, availablePrinters()) { + if (printerInfo.printerName() == printer.printerName()) { + d_ptr.reset(new QPrinterInfoPrivate(*printerInfo.d_ptr)); + break; + } + } +} + +/*! + \internal +*/ +QPrinterInfo::QPrinterInfo(const QString &name) + : d_ptr(new QPrinterInfoPrivate(name)) +{ +} + +/*! + Destroys the QPrinterInfo object. References to the values in the + object become invalid. +*/ +QPrinterInfo::~QPrinterInfo() +{ +} + +/*! + Sets the QPrinterInfo object to be equal to \a other. +*/ +QPrinterInfo &QPrinterInfo::operator=(const QPrinterInfo &other) +{ + Q_ASSERT(d_ptr); + d_ptr.reset(new QPrinterInfoPrivate(*other.d_ptr)); + return *this; +} + +/*! + Returns the name of the printer. + + \sa QPrinter::setPrinterName() +*/ +QString QPrinterInfo::printerName() const +{ + const Q_D(QPrinterInfo); + return d->name; +} + +/*! + Returns whether this QPrinterInfo object holds a printer definition. + + An empty QPrinterInfo object could result for example from calling + defaultPrinter() when there are no printers on the system. +*/ +bool QPrinterInfo::isNull() const +{ + const Q_D(QPrinterInfo); + return d == &QPrinterInfoPrivate::shared_null; +} + +/*! + Returns whether this printer is the default printer. +*/ +bool QPrinterInfo::isDefault() const +{ + const Q_D(QPrinterInfo); + return d->isDefault; +} + +/*! + \fn QList< QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const + \since 4.4 + + Returns a list of supported paper sizes by the printer. + + Not all printer drivers support this query, so the list may be empty. + On Mac OS X 10.3, this function always returns an empty list. +*/ + +#ifdef Q_WS_QPA +QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const +{ + const Q_D(QPrinterInfo); + if (!isNull() && !d->hasPaperSizes) { + d->paperSizes = QPlatformPrinterSupportPlugin::get()->supportedPaperSizes(*this); + d->hasPaperSizes = true; + } + return d->paperSizes; +} + +QList<QPrinterInfo> QPrinterInfo::availablePrinters() +{ + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (!ps) + return QList<QPrinterInfo>(); + return ps->availablePrinters(); +} + +QPrinterInfo QPrinterInfo::defaultPrinter() +{ + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (!ps) + return QPrinterInfo(); + return QPlatformPrinterSupportPlugin::get()->defaultPrinter(); +} + +#endif //Q_WS_QPA + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qprinterinfo.h b/src/printsupport/kernel/qprinterinfo.h new file mode 100644 index 0000000000..535c29c4d6 --- /dev/null +++ b/src/printsupport/kernel/qprinterinfo.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINTERINFO_H +#define QPRINTERINFO_H + +#include <QtCore/QList> + +#include <QtPrintSupport/QPrinter> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_PRINTER +class QPrinterInfoPrivate; +class QPrinterInfoPrivateDeleter; +class Q_PRINTSUPPORT_EXPORT QPrinterInfo +{ +public: + QPrinterInfo(); + QPrinterInfo(const QPrinterInfo &other); + QPrinterInfo(const QPrinter &printer); + ~QPrinterInfo(); + + QPrinterInfo &operator=(const QPrinterInfo &other); + + QString printerName() const; + bool isNull() const; + bool isDefault() const; + QList<QPrinter::PaperSize> supportedPaperSizes() const; + + static QList<QPrinterInfo> availablePrinters(); + static QPrinterInfo defaultPrinter(); + +private: + QPrinterInfo(const QString &name); + +private: + friend class QPlatformPrinterSupport; + Q_DECLARE_PRIVATE(QPrinterInfo) + QScopedPointer<QPrinterInfoPrivate, QPrinterInfoPrivateDeleter> d_ptr; +}; + +#endif // QT_NO_PRINTER + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPRINTERINFO_H diff --git a/src/printsupport/kernel/qprinterinfo_p.h b/src/printsupport/kernel/qprinterinfo_p.h new file mode 100644 index 0000000000..a3c654e7b7 --- /dev/null +++ b/src/printsupport/kernel/qprinterinfo_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINTERINFO_P_H +#define QPRINTERINFO_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qglobal.h" + +#ifndef QT_NO_PRINTER + +#include "QtCore/qlist.h" + +QT_BEGIN_NAMESPACE + +class QPrinterInfoPrivate +{ +public: + QPrinterInfoPrivate(const QString& name = QString()) : + name(name), isDefault(false) +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)) || defined(Q_WS_QPA) +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + , cupsPrinterIndex(0) +#endif +#endif + , hasPaperSizes(false) + {} + ~QPrinterInfoPrivate() + {} + + static QPrinterInfoPrivate shared_null; + + QString name; + bool isDefault; + +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)) || defined(Q_WS_QPA) +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + int cupsPrinterIndex; +#endif +#endif + mutable bool hasPaperSizes; + mutable QList<QPrinter::PaperSize> paperSizes; +}; + + +class QPrinterInfoPrivateDeleter +{ +public: + static inline void cleanup(QPrinterInfoPrivate *d) + { + if (d != &QPrinterInfoPrivate::shared_null) + delete d; + } +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER + +#endif // QPRINTERINFO_P_H diff --git a/src/printsupport/kernel/qprinterinfo_unix.cpp b/src/printsupport/kernel/qprinterinfo_unix.cpp new file mode 100644 index 0000000000..c7dbb7cc32 --- /dev/null +++ b/src/printsupport/kernel/qprinterinfo_unix.cpp @@ -0,0 +1,857 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qprinterinfo.h" +#include "qprinterinfo_p.h" + +#include <qfile.h> +#include <qfileinfo.h> +#include <qdir.h> +#include <qlibrary.h> +#include <qtextstream.h> +#include <qcoreapplication.h> + +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) +# include <private/qcups_p.h> +# include <cups/cups.h> +# include <private/qpdf_p.h> +#endif + +#include <private/qprinterinfo_unix_p.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PRINTER + +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) +// preserver names in ascending order for the binary search +static const struct NamedPaperSize { + const char *const name; + QPrinter::PaperSize size; +} named_sizes_map[QPrinter::NPageSize] = { + { "A0", QPrinter::A0 }, + { "A1", QPrinter::A1 }, + { "A2", QPrinter::A2 }, + { "A3", QPrinter::A3 }, + { "A4", QPrinter::A4 }, + { "A5", QPrinter::A5 }, + { "A6", QPrinter::A6 }, + { "A7", QPrinter::A7 }, + { "A8", QPrinter::A8 }, + { "A9", QPrinter::A9 }, + { "B0", QPrinter::B0 }, + { "B1", QPrinter::B1 }, + { "B10", QPrinter::B10 }, + { "B2", QPrinter::B2 }, + { "B4", QPrinter::B4 }, + { "B5", QPrinter::B5 }, + { "B6", QPrinter::B6 }, + { "B7", QPrinter::B7 }, + { "B8", QPrinter::B8 }, + { "B9", QPrinter::B9 }, + { "C5E", QPrinter::C5E }, + { "Comm10E", QPrinter::Comm10E }, + { "Custom", QPrinter::Custom }, + { "DLE", QPrinter::DLE }, + { "Executive", QPrinter::Executive }, + { "Folio", QPrinter::Folio }, + { "Ledger", QPrinter::Ledger }, + { "Legal", QPrinter::Legal }, + { "Letter", QPrinter::Letter }, + { "Tabloid", QPrinter::Tabloid } +}; + +inline bool operator<(const char *name, const NamedPaperSize &data) +{ return qstrcmp(name, data.name) < 0; } +inline bool operator<(const NamedPaperSize &data, const char *name) +{ return qstrcmp(data.name, name) < 0; } + +static inline QPrinter::PaperSize string2PaperSize(const char *name) +{ + const NamedPaperSize *r = qBinaryFind(named_sizes_map, named_sizes_map + QPrinter::NPageSize, name); + if (r - named_sizes_map != QPrinter::NPageSize) + return r->size; + return QPrinter::Custom; +} + +static inline const char *paperSize2String(QPrinter::PaperSize size) +{ + for (int i = 0; i < QPrinter::NPageSize; ++i) { + if (size == named_sizes_map[i].size) + return named_sizes_map[i].name; + } + return 0; +} +#endif + +void qt_perhapsAddPrinter(QList<QPrinterDescription> *printers, const QString &name, + QString host, QString comment, + QStringList aliases) +{ + for (int i = 0; i < printers->size(); ++i) + if (printers->at(i).samePrinter(name)) + return; + + if (host.isEmpty()) + host = QCoreApplication::translate("QPrinter", "locally connected"); + printers->append(QPrinterDescription(name.simplified(), host.simplified(), comment.simplified(), aliases)); +} + +void qt_parsePrinterDesc(QString printerDesc, QList<QPrinterDescription> *printers) +{ + if (printerDesc.length() < 1) + return; + + printerDesc = printerDesc.simplified(); + int i = printerDesc.indexOf(QLatin1Char(':')); + QString printerName, printerComment, printerHost; + QStringList aliases; + + if (i >= 0) { + // have ':' want '|' + int j = printerDesc.indexOf(QLatin1Char('|')); + if (j > 0 && j < i) { + printerName = printerDesc.left(j); + aliases = printerDesc.mid(j + 1, i - j - 1).split(QLatin1Char('|')); + // try extracting a comment from the aliases + printerComment = QCoreApplication::translate("QPrinter", "Aliases: %1") + .arg(aliases.join(QLatin1String(", "))); + } else { + printerName = printerDesc.left(i); + } + // look for lprng pseudo all printers entry + i = printerDesc.indexOf(QRegExp(QLatin1String(": *all *="))); + if (i >= 0) + printerName = QString(); + // look for signs of this being a remote printer + i = printerDesc.indexOf(QRegExp(QLatin1String(": *rm *="))); + if (i >= 0) { + // point k at the end of remote host name + while (printerDesc[i] != QLatin1Char('=')) + i++; + while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace()) + i++; + j = i; + while (j < (int)printerDesc.length() && printerDesc[j] != QLatin1Char(':')) + j++; + + // and stuff that into the string + printerHost = printerDesc.mid(i, j - i); + } + } + if (printerName.length()) + qt_perhapsAddPrinter(printers, printerName, printerHost, printerComment, + aliases); +} + +int qt_parsePrintcap(QList<QPrinterDescription> *printers, const QString& fileName) +{ + QFile printcap(fileName); + if (!printcap.open(QIODevice::ReadOnly)) + return NotFound; + + char *line_ascii = new char[1025]; + line_ascii[1024] = '\0'; + + QString printerDesc; + bool atEnd = false; + + while (!atEnd) { + if (printcap.atEnd() || printcap.readLine(line_ascii, 1024) <= 0) + atEnd = true; + QString line = QString::fromLocal8Bit(line_ascii); + line = line.trimmed(); + if (line.length() >= 1 && line[int(line.length()) - 1] == QLatin1Char('\\')) + line.chop(1); + if (line[0] == QLatin1Char('#')) { + if (!atEnd) + continue; + } else if (line[0] == QLatin1Char('|') || line[0] == QLatin1Char(':') + || line.isEmpty()) { + printerDesc += line; + if (!atEnd) + continue; + } + + qt_parsePrinterDesc(printerDesc, printers); + + // add the first line of the new printer definition + printerDesc = line; + } + delete[] line_ascii; + return Success; +} + +/*! + \internal + + Checks $HOME/.printers for a line matching '_default <name>' (where + <name> does not contain any white space). The first such match + results in <name> being returned. + If no lines match then an empty string is returned. +*/ +QString qt_getDefaultFromHomePrinters() +{ + QFile file(QDir::homePath() + QLatin1String("/.printers")); + if (!file.open(QIODevice::ReadOnly)) + return QString(); + QString all(QLatin1String(file.readAll())); + QStringList words = all.split(QRegExp(QLatin1String("\\W+")), QString::SkipEmptyParts); + const int i = words.indexOf(QLatin1String("_default")); + if (i != -1 && i < words.size() - 1) + return words.at(i + 1); + return QString(); +} + +// solaris, not 2.6 +void qt_parseEtcLpPrinters(QList<QPrinterDescription> *printers) +{ + QDir lp(QLatin1String("/etc/lp/printers")); + QFileInfoList dirs = lp.entryInfoList(); + if (dirs.isEmpty()) + return; + + QString tmp; + for (int i = 0; i < dirs.size(); ++i) { + QFileInfo printer = dirs.at(i); + if (printer.isDir()) { + tmp.sprintf("/etc/lp/printers/%s/configuration", + printer.fileName().toAscii().data()); + QFile configuration(tmp); + char *line = new char[1025]; + QString remote(QLatin1String("Remote:")); + QString contentType(QLatin1String("Content types:")); + QString printerHost; + bool canPrintPostscript = false; + if (configuration.open(QIODevice::ReadOnly)) { + while (!configuration.atEnd() && + configuration.readLine(line, 1024) > 0) { + if (QString::fromLatin1(line).startsWith(remote)) { + const char *p = line; + while (*p != ':') + p++; + p++; + while (isspace((uchar) *p)) + p++; + printerHost = QString::fromLocal8Bit(p); + printerHost = printerHost.simplified(); + } else if (QString::fromLatin1(line).startsWith(contentType)) { + char *p = line; + while (*p != ':') + p++; + p++; + char *e; + while (*p) { + while (isspace((uchar) *p)) + p++; + if (*p) { + char s; + e = p; + while (isalnum((uchar) *e)) + e++; + s = *e; + *e = '\0'; + if (!qstrcmp(p, "postscript") || + !qstrcmp(p, "any")) + canPrintPostscript = true; + *e = s; + if (s == ',') + e++; + p = e; + } + } + } + } + if (canPrintPostscript) + qt_perhapsAddPrinter(printers, printer.fileName(), + printerHost, QLatin1String("")); + } + delete[] line; + } + } +} + +// solaris 2.6 +char *qt_parsePrintersConf(QList<QPrinterDescription> *printers, bool *found) +{ + QFile pc(QLatin1String("/etc/printers.conf")); + if (!pc.open(QIODevice::ReadOnly)) { + if (found) + *found = false; + return 0; + } + if (found) + *found = true; + + char *line = new char[1025]; + line[1024] = '\0'; + + QString printerDesc; + int lineLength = 0; + + char *defaultPrinter = 0; + + while (!pc.atEnd() && + (lineLength=pc.readLine(line, 1024)) > 0) { + if (*line == '#') { + *line = '\0'; + lineLength = 0; + } + if (lineLength >= 2 && line[lineLength-2] == '\\') { + line[lineLength-2] = '\0'; + printerDesc += QString::fromLocal8Bit(line); + } else { + printerDesc += QString::fromLocal8Bit(line); + printerDesc = printerDesc.simplified(); + int i = printerDesc.indexOf(QLatin1Char(':')); + QString printerName, printerHost, printerComment; + QStringList aliases; + if (i >= 0) { + // have : want | + int j = printerDesc.indexOf(QLatin1Char('|')); + if (j >= i) + j = -1; + printerName = printerDesc.mid(0, j < 0 ? i : j); + if (printerName == QLatin1String("_default")) { + i = printerDesc.indexOf( + QRegExp(QLatin1String(": *use *="))); + while (printerDesc[i] != QLatin1Char('=')) + i++; + while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace()) + i++; + j = i; + while (j < (int)printerDesc.length() && + printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(',')) + j++; + // that's our default printer + defaultPrinter = + qstrdup(printerDesc.mid(i, j-i).toAscii().data()); + printerName = QString(); + printerDesc = QString(); + } else if (printerName == QLatin1String("_all")) { + // skip it.. any other cases we want to skip? + printerName = QString(); + printerDesc = QString(); + } + + if (j > 0) { + // try extracting a comment from the aliases + aliases = printerDesc.mid(j + 1, i - j - 1).split(QLatin1Char('|')); + printerComment = QCoreApplication::translate("QPrinter", "Aliases: %1") + .arg(aliases.join(QLatin1String(", "))); + } + // look for signs of this being a remote printer + i = printerDesc.indexOf( + QRegExp(QLatin1String(": *bsdaddr *="))); + if (i >= 0) { + // point k at the end of remote host name + while (printerDesc[i] != QLatin1Char('=')) + i++; + while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace()) + i++; + j = i; + while (j < (int)printerDesc.length() && + printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(',')) + j++; + // and stuff that into the string + printerHost = printerDesc.mid(i, j-i); + // maybe stick the remote printer name into the comment + if (printerDesc[j] == QLatin1Char(',')) { + i = ++j; + while (printerDesc[i].isSpace()) + i++; + j = i; + while (j < (int)printerDesc.length() && + printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(',')) + j++; + if (printerName != printerDesc.mid(i, j-i)) { + printerComment = + QLatin1String("Remote name: "); + printerComment += printerDesc.mid(i, j-i); + } + } + } + } + if (printerComment == QLatin1String(":")) + printerComment = QString(); // for cups + if (printerName.length()) + qt_perhapsAddPrinter(printers, printerName, printerHost, + printerComment, aliases); + // chop away the line, for processing the next one + printerDesc = QString(); + } + } + delete[] line; + return defaultPrinter; +} + +#ifndef QT_NO_NIS + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +int qt_pd_foreach(int /*status */, char * /*key */, int /*keyLen */, + char *val, int valLen, char *data) +{ + qt_parsePrinterDesc(QString::fromLatin1(val, valLen), (QList<QPrinterDescription> *)data); + return 0; +} + +#if defined(Q_C_CALLBACKS) +} +#endif + +int qt_retrieveNisPrinters(QList<QPrinterDescription> *printers) +{ +#ifndef QT_NO_LIBRARY + typedef int (*WildCast)(int, char *, int, char *, int, char *); + char printersConfByname[] = "printers.conf.byname"; + char *domain; + int err; + + QLibrary lib(QLatin1String("nsl")); + typedef int (*ypGetDefaultDomain)(char **); + ypGetDefaultDomain _ypGetDefaultDomain = (ypGetDefaultDomain)lib.resolve("yp_get_default_domain"); + typedef int (*ypAll)(const char *, const char *, const struct ypall_callback *); + ypAll _ypAll = (ypAll)lib.resolve("yp_all"); + + if (_ypGetDefaultDomain && _ypAll) { + err = _ypGetDefaultDomain(&domain); + if (err == 0) { + ypall_callback cb; + // wild cast to support K&R-style system headers + (WildCast &) cb.foreach = (WildCast) qt_pd_foreach; + cb.data = (char *) printers; + err = _ypAll(domain, printersConfByname, &cb); + } + if (!err) + return Success; + } +#endif //QT_NO_LIBRARY + return Unavail; +} + +#endif // QT_NO_NIS + +char *qt_parseNsswitchPrintersEntry(QList<QPrinterDescription> *printers, char *line) +{ +#define skipSpaces() \ + while (line[k] != '\0' && isspace((uchar) line[k])) \ + k++ + + char *defaultPrinter = 0; + bool stop = false; + int lastStatus = NotFound; + + int k = 8; + skipSpaces(); + if (line[k] != ':') + return 0; + k++; + + char *cp = strchr(line, '#'); + if (cp != 0) + *cp = '\0'; + + while (line[k] != '\0') { + if (isspace((uchar) line[k])) { + k++; + } else if (line[k] == '[') { + k++; + skipSpaces(); + while (line[k] != '\0') { + char status = tolower(line[k]); + char action = '?'; + + while (line[k] != '=' && line[k] != ']' && line[k] != '\0') + k++; + if (line[k] == '=') { + k++; + skipSpaces(); + action = tolower(line[k]); + while (line[k] != '\0' && !isspace((uchar) line[k]) && line[k] != ']') + k++; + } else if (line[k] == ']') { + k++; + break; + } + skipSpaces(); + + if (lastStatus == status) + stop = (action == (char) Return); + } + } else { + if (stop) + break; + + QByteArray source; + while (line[k] != '\0' && !isspace((uchar) line[k]) && line[k] != '[') { + source += line[k]; + k++; + } + + if (source == "user") { + lastStatus = qt_parsePrintcap(printers, + QDir::homePath() + QLatin1String("/.printers")); + } else if (source == "files") { + bool found; + defaultPrinter = qt_parsePrintersConf(printers, &found); + if (found) + lastStatus = Success; +#ifndef QT_NO_NIS + } else if (source == "nis") { + lastStatus = qt_retrieveNisPrinters(printers); +#endif + } else { + // nisplus, dns, etc., are not implemented yet + lastStatus = NotFound; + } + stop = (lastStatus == Success); + } + } + return defaultPrinter; +} + +char *qt_parseNsswitchConf(QList<QPrinterDescription> *printers) +{ + QFile nc(QLatin1String("/etc/nsswitch.conf")); + if (!nc.open(QIODevice::ReadOnly)) + return 0; + + char *defaultPrinter = 0; + + char *line = new char[1025]; + line[1024] = '\0'; + + while (!nc.atEnd() && + nc.readLine(line, 1024) > 0) { + if (qstrncmp(line, "printers", 8) == 0) { + defaultPrinter = qt_parseNsswitchPrintersEntry(printers, line); + delete[] line; + return defaultPrinter; + } + } + + strcpy(line, "printers: user files nis nisplus xfn"); + defaultPrinter = qt_parseNsswitchPrintersEntry(printers, line); + delete[] line; + return defaultPrinter; +} + +// HP-UX +void qt_parseEtcLpMember(QList<QPrinterDescription> *printers) +{ + QDir lp(QLatin1String("/etc/lp/member")); + if (!lp.exists()) + return; + QFileInfoList dirs = lp.entryInfoList(); + if (dirs.isEmpty()) + return; + + QString tmp; + for (int i = 0; i < dirs.size(); ++i) { + QFileInfo printer = dirs.at(i); + // I haven't found any real documentation, so I'm guessing that + // since lpstat uses /etc/lp/member rather than one of the + // other directories, it's the one to use. I did not find a + // decent way to locate aliases and remote printers. + if (printer.isFile()) + qt_perhapsAddPrinter(printers, printer.fileName(), + QCoreApplication::translate("QPrinter", "unknown"), + QLatin1String("")); + } +} + +// IRIX 6.x +void qt_parseSpoolInterface(QList<QPrinterDescription> *printers) +{ + QDir lp(QLatin1String("/usr/spool/lp/interface")); + if (!lp.exists()) + return; + QFileInfoList files = lp.entryInfoList(); + if(files.isEmpty()) + return; + + for (int i = 0; i < files.size(); ++i) { + QFileInfo printer = files.at(i); + + if (!printer.isFile()) + continue; + + // parse out some information + QFile configFile(printer.filePath()); + if (!configFile.open(QIODevice::ReadOnly)) + continue; + + QByteArray line; + line.resize(1025); + QString namePrinter; + QString hostName; + QString hostPrinter; + QString printerType; + + QString nameKey(QLatin1String("NAME=")); + QString typeKey(QLatin1String("TYPE=")); + QString hostKey(QLatin1String("HOSTNAME=")); + QString hostPrinterKey(QLatin1String("HOSTPRINTER=")); + + while (!configFile.atEnd() && + (configFile.readLine(line.data(), 1024)) > 0) { + QString uline = QString::fromLocal8Bit(line); + if (uline.startsWith(typeKey) ) { + printerType = uline.mid(nameKey.length()); + printerType = printerType.simplified(); + } else if (uline.startsWith(hostKey)) { + hostName = uline.mid(hostKey.length()); + hostName = hostName.simplified(); + } else if (uline.startsWith(hostPrinterKey)) { + hostPrinter = uline.mid(hostPrinterKey.length()); + hostPrinter = hostPrinter.simplified(); + } else if (uline.startsWith(nameKey)) { + namePrinter = uline.mid(nameKey.length()); + namePrinter = namePrinter.simplified(); + } + } + configFile.close(); + + printerType = printerType.trimmed(); + if (printerType.indexOf(QLatin1String("postscript"), 0, Qt::CaseInsensitive) < 0) + continue; + + int ii = 0; + while ((ii = namePrinter.indexOf(QLatin1Char('"'), ii)) >= 0) + namePrinter.remove(ii, 1); + + if (hostName.isEmpty() || hostPrinter.isEmpty()) { + qt_perhapsAddPrinter(printers, printer.fileName(), + QLatin1String(""), namePrinter); + } else { + QString comment; + comment = namePrinter; + comment += QLatin1String(" ("); + comment += hostPrinter; + comment += QLatin1Char(')'); + qt_perhapsAddPrinter(printers, printer.fileName(), + hostName, comment); + } + } +} + + +// Every unix must have its own. It's a standard. Here is AIX. +void qt_parseQconfig(QList<QPrinterDescription> *printers) +{ + QFile qconfig(QLatin1String("/etc/qconfig")); + if (!qconfig.open(QIODevice::ReadOnly)) + return; + + QTextStream ts(&qconfig); + QString line; + + QString stanzaName; // either a queue or a device name + bool up = true; // queue up? default true, can be false + QString remoteHost; // null if local + QString deviceName; // null if remote + + QRegExp newStanza(QLatin1String("^[0-z\\-]*:$")); + + // our basic strategy here is to process each line, detecting new + // stanzas. each time we see a new stanza, we check if the + // previous stanza was a valid queue for a) a remote printer or b) + // a local printer. if it wasn't, we assume that what we see is + // the start of the first stanza, or that the previous stanza was + // a device stanza, or that there is some syntax error (we don't + // report those). + + do { + line = ts.readLine(); + bool indented = line[0].isSpace(); + line = line.simplified(); + + int i = line.indexOf(QLatin1Char('=')); + if (indented && i != -1) { // line in stanza + QString variable = line.left(i).simplified(); + QString value=line.mid(i+1, line.length()).simplified(); + if (variable == QLatin1String("device")) + deviceName = value; + else if (variable == QLatin1String("host")) + remoteHost = value; + else if (variable == QLatin1String("up")) + up = !(value.toLower() == QLatin1String("false")); + } else if (line[0] == QLatin1Char('*')) { // comment + // nothing to do + } else if (ts.atEnd() || // end of file, or beginning of new stanza + (!indented && line.contains(newStanza))) { + if (up && stanzaName.length() > 0 && stanzaName.length() < 21) { + if (remoteHost.length()) // remote printer + qt_perhapsAddPrinter(printers, stanzaName, remoteHost, + QString()); + else if (deviceName.length()) // local printer + qt_perhapsAddPrinter(printers, stanzaName, QString(), + QString()); + } + line.chop(1); + if (line.length() >= 1 && line.length() <= 20) + stanzaName = line; + up = true; + remoteHost.clear(); + deviceName.clear(); + } else { + // syntax error? ignore. + } + } while (!ts.atEnd()); +} + +Q_PRINTSUPPORT_EXPORT int qt_getLprPrinters(QList<QPrinterDescription>& printers) +{ + QByteArray etcLpDefault; + qt_parsePrintcap(&printers, QLatin1String("/etc/printcap")); + qt_parseEtcLpMember(&printers); + qt_parseSpoolInterface(&printers); + qt_parseQconfig(&printers); + + QFileInfo f; + f.setFile(QLatin1String("/etc/lp/printers")); + if (f.isDir()) { + qt_parseEtcLpPrinters(&printers); + QFile def(QLatin1String("/etc/lp/default")); + if (def.open(QIODevice::ReadOnly)) { + etcLpDefault.resize(1025); + if (def.readLine(etcLpDefault.data(), 1024) > 0) { + QRegExp rx(QLatin1String("^(\\S+)")); + if (rx.indexIn(QString::fromLatin1(etcLpDefault)) != -1) + etcLpDefault = rx.cap(1).toAscii(); + } + } + } + + char *def = 0; + f.setFile(QLatin1String("/etc/nsswitch.conf")); + if (f.isFile()) { + def = qt_parseNsswitchConf(&printers); + } else { + f.setFile(QLatin1String("/etc/printers.conf")); + if (f.isFile()) + def = qt_parsePrintersConf(&printers); + } + + if (def) { + etcLpDefault = def; + delete [] def; + } + + QString homePrintersDefault = qt_getDefaultFromHomePrinters(); + + // all printers hopefully known. try to find a good default + QString dollarPrinter; + { + dollarPrinter = QString::fromLocal8Bit(qgetenv("PRINTER")); + if (dollarPrinter.isEmpty()) + dollarPrinter = QString::fromLocal8Bit(qgetenv("LPDEST")); + if (dollarPrinter.isEmpty()) + dollarPrinter = QString::fromLocal8Bit(qgetenv("NPRINTER")); + if (dollarPrinter.isEmpty()) + dollarPrinter = QString::fromLocal8Bit(qgetenv("NGPRINTER")); + if (!dollarPrinter.isEmpty()) + qt_perhapsAddPrinter(&printers, dollarPrinter, + QCoreApplication::translate("QPrinter", "unknown"), + QLatin1String("")); + } + + QRegExp ps(QLatin1String("[^a-z]ps(?:[^a-z]|$)")); + QRegExp lp(QLatin1String("[^a-z]lp(?:[^a-z]|$)")); + + int quality = 0; + int best = 0; + for (int i = 0; i < printers.size(); ++i) { + QString name = printers.at(i).name; + QString comment = printers.at(i).comment; + if (quality < 5 && name == dollarPrinter) { + best = i; + quality = 5; + } else if (quality < 4 && !homePrintersDefault.isEmpty() && + name == homePrintersDefault) { + best = i; + quality = 4; + } else if (quality < 3 && !etcLpDefault.isEmpty() && + name == QLatin1String(etcLpDefault)) { + best = i; + quality = 3; + } else if (quality < 2 && + (name == QLatin1String("ps") || + ps.indexIn(comment) != -1)) { + best = i; + quality = 2; + } else if (quality < 1 && + (name == QLatin1String("lp") || + lp.indexIn(comment) > -1)) { + best = i; + quality = 1; + } + } + + return best; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +QList<QPrinter::PaperSize> qt_getCupsPrinterPaperSizes(int cupsPrinterIndex) +{ + QList<QPrinter::PaperSize> result; +#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) + if (!QCUPSSupport::isAvailable() || cupsPrinterIndex < 0) + return result; + // Find paper sizes from CUPS. + QCUPSSupport cups; + cups.setCurrentPrinter(cupsPrinterIndex); + if (const ppd_option_t* size = cups.pageSizes()) { + for (int j = 0; j < size->num_choices; ++j) + result.append(string2PaperSize(size->choices[j].choice)); + } + return result; +#endif +} + +#endif // QT_NO_PRINTER + +QT_END_NAMESPACE diff --git a/src/printsupport/kernel/qprinterinfo_unix_p.h b/src/printsupport/kernel/qprinterinfo_unix_p.h new file mode 100644 index 0000000000..c12aa39556 --- /dev/null +++ b/src/printsupport/kernel/qprinterinfo_unix_p.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRINTERINFO_UNIX_P_H +#define QPRINTERINFO_UNIX_P_H + +#include <QtPrintSupport/qprinter.h> +#include <QtCore/qstringlist.h> + +#ifndef QT_NO_NIS +# ifndef BOOL_DEFINED +# define BOOL_DEFINED +# endif + +# include <sys/types.h> +# include <rpc/rpc.h> +# include <rpcsvc/ypclnt.h> +# include <rpcsvc/yp_prot.h> +#endif // QT_NO_NIS + +#ifdef Success +# undef Success +#endif + +#include <ctype.h> + +QT_BEGIN_NAMESPACE + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QT_NO_PRINTER + +struct QPrinterDescription { + QPrinterDescription(const QString &n, const QString &h, const QString &c, const QStringList &a) + : name(n), host(h), comment(c), aliases(a) {} + QString name; + QString host; + QString comment; + QStringList aliases; + bool samePrinter(const QString& printer) const { + return name == printer || aliases.contains(printer); + } +}; + +enum { Success = 's', Unavail = 'u', NotFound = 'n', TryAgain = 't' }; +enum { Continue = 'c', Return = 'r' }; + +void qt_perhapsAddPrinter(QList<QPrinterDescription> *printers, const QString &name, + QString host, QString comment, + QStringList aliases = QStringList()); +void qt_parsePrinterDesc(QString printerDesc, QList<QPrinterDescription> *printers); + +int qt_parsePrintcap(QList<QPrinterDescription> *printers, const QString& fileName); +QString qt_getDefaultFromHomePrinters(); +void qt_parseEtcLpPrinters(QList<QPrinterDescription> *printers); +char *qt_parsePrintersConf(QList<QPrinterDescription> *printers, bool *found = 0); + +#ifndef QT_NO_NIS +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif +int qt_pd_foreach(int /*status */, char * /*key */, int /*keyLen */, + char *val, int valLen, char *data); + +#if defined(Q_C_CALLBACKS) +} +#endif +int qt_retrieveNisPrinters(QList<QPrinterDescription> *printers); +#endif // QT_NO_NIS +char *qt_parseNsswitchPrintersEntry(QList<QPrinterDescription> *printers, char *line); +char *qt_parseNsswitchConf(QList<QPrinterDescription> *printers); +void qt_parseEtcLpMember(QList<QPrinterDescription> *printers); +void qt_parseSpoolInterface(QList<QPrinterDescription> *printers); +void qt_parseQconfig(QList<QPrinterDescription> *printers); +int qt_getLprPrinters(QList<QPrinterDescription>& printers); + +QList<QPrinter::PaperSize> qt_getCupsPrinterPaperSizes(int cupsPrinterIndex); + +#endif // QT_NO_PRINTER + +QT_END_NAMESPACE + +#endif // QPRINTERINFO_UNIX_P_H |