Qt源码解析-Qt linux打印机封装类QCUPSSupport

公众号:Qt那些事儿

公众号


q_cups_p.h

#ifndef QCUPS_P_H
#define QCUPS_P_H


//#include "QtCore/qstring.h"
//#include "QtCore/qstringlist.h"
//#include "QtGui/qprinter.h"
#include <QString>
#include <QStringList>
#include <QtPrintSupport/qprinter.h>

#ifndef QT_NO_CUPS
//#include <QtCore/qlibrary.h>
#include <cups/cups.h>
#include <cups/ppd.h>
#include <QLibrary>

QT_BEGIN_NAMESPACE

Q_DECLARE_TYPEINFO(cups_option_t, Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE);

class QCUPSSupport
{
public:
	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);

// add by zhangpf
public:
	const char* getCurrentPrinterName(int index) const;
	int getCurrentPrinter(const char* name);


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


q_cups.cpp

#include <qdebug.h>
#include "qcups_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;

    // Update the available printer count
    qt_cups_num_printers = 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 char* QCUPSSupport::getCurrentPrinterName(int index) const
{
	Q_ASSERT(index >= 0 && index <= prnCount);
	return printers[index].name;
}

int QCUPSSupport::getCurrentPrinter(const char* name)
{
	for (int i = 0; i < prnCount; i++)
	{
		if (name == printers[i].name)
			return i;
	}

	return -1;
}

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);
}

QT_END_NAMESPACE

#endif // QT_NO_CUPS

公众号:Qt那些事儿

公众号

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值