PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/qtopiacore/qt/src/gui/painting/qcups.cpp

https://github.com/Fale/qtmoko
C++ | 398 lines | 294 code | 53 blank | 51 comment | 53 complexity | bae2255bacc1d2569974ab738e8b5e10 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.1, LGPL-3.0, BSD-3-Clause, GPL-3.0
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
  4. ** Contact: Qt Software Information (qt-info@nokia.com)
  5. **
  6. ** This file is part of the QtGui module of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:LGPL$
  9. ** Commercial Usage
  10. ** Licensees holding valid Qt Commercial licenses may use this file in
  11. ** accordance with the Qt Commercial License Agreement provided with the
  12. ** Software or, alternatively, in accordance with the terms contained in
  13. ** a written agreement between you and Nokia.
  14. **
  15. ** GNU Lesser General Public License Usage
  16. ** Alternatively, this file may be used under the terms of the GNU Lesser
  17. ** General Public License version 2.1 as published by the Free Software
  18. ** Foundation and appearing in the file LICENSE.LGPL included in the
  19. ** packaging of this file. Please review the following information to
  20. ** ensure the GNU Lesser General Public License version 2.1 requirements
  21. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  22. **
  23. ** In addition, as a special exception, Nokia gives you certain
  24. ** additional rights. These rights are described in the Nokia Qt LGPL
  25. ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
  26. ** package.
  27. **
  28. ** GNU General Public License Usage
  29. ** Alternatively, this file may be used under the terms of the GNU
  30. ** General Public License version 3.0 as published by the Free Software
  31. ** Foundation and appearing in the file LICENSE.GPL included in the
  32. ** packaging of this file. Please review the following information to
  33. ** ensure the GNU General Public License version 3.0 requirements will be
  34. ** met: http://www.gnu.org/copyleft/gpl.html.
  35. **
  36. ** If you are unsure which license is appropriate for your use, please
  37. ** contact the sales department at qt-sales@nokia.com.
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include <qdebug.h>
  42. #include "qcups_p.h"
  43. #ifndef QT_NO_CUPS
  44. #ifndef QT_LINUXBASE // LSB merges everything into cups.h
  45. # include <cups/language.h>
  46. #endif
  47. #include <qtextcodec.h>
  48. QT_BEGIN_NAMESPACE
  49. typedef int (*CupsGetDests)(cups_dest_t **dests);
  50. typedef void (*CupsFreeDests)(int num_dests, cups_dest_t *dests);
  51. typedef const char* (*CupsGetPPD)(const char *printer);
  52. typedef int (*CupsMarkOptions)(ppd_file_t *ppd, int num_options, cups_option_t *options);
  53. typedef ppd_file_t* (*PPDOpenFile)(const char *filename);
  54. typedef void (*PPDMarkDefaults)(ppd_file_t *ppd);
  55. typedef int (*PPDMarkOption)(ppd_file_t *ppd, const char *keyword, const char *option);
  56. typedef void (*PPDClose)(ppd_file_t *ppd);
  57. typedef int (*PPDMarkOption)(ppd_file_t *ppd, const char *keyword, const char *option);
  58. typedef void (*CupsFreeOptions)(int num_options, cups_option_t *options);
  59. typedef void (*CupsSetDests)(int num_dests, cups_dest_t *dests);
  60. typedef cups_lang_t* (*CupsLangGet)(const char *language);
  61. typedef const char* (*CupsLangEncoding)(cups_lang_t *language);
  62. typedef int (*CupsAddOption)(const char *name, const char *value, int num_options, cups_option_t **options);
  63. typedef int (*CupsTempFd)(char *name, int len);
  64. typedef int (*CupsPrintFile)(const char * name, const char * filename, const char * title, int num_options, cups_option_t * options);
  65. static bool cupsLoaded = false;
  66. static int qt_cups_num_printers = 0;
  67. static CupsGetDests _cupsGetDests = 0;
  68. static CupsFreeDests _cupsFreeDests = 0;
  69. static CupsGetPPD _cupsGetPPD = 0;
  70. static PPDOpenFile _ppdOpenFile = 0;
  71. static PPDMarkDefaults _ppdMarkDefaults = 0;
  72. static PPDClose _ppdClose = 0;
  73. static CupsMarkOptions _cupsMarkOptions = 0;
  74. static PPDMarkOption _ppdMarkOption = 0;
  75. static CupsFreeOptions _cupsFreeOptions = 0;
  76. static CupsSetDests _cupsSetDests = 0;
  77. static CupsLangGet _cupsLangGet = 0;
  78. static CupsLangEncoding _cupsLangEncoding = 0;
  79. static CupsAddOption _cupsAddOption = 0;
  80. static CupsTempFd _cupsTempFd = 0;
  81. static CupsPrintFile _cupsPrintFile = 0;
  82. static void resolveCups()
  83. {
  84. QLibrary cupsLib(QLatin1String("cups"), 2);
  85. if(cupsLib.load()) {
  86. _cupsGetDests = (CupsGetDests) cupsLib.resolve("cupsGetDests");
  87. _cupsFreeDests = (CupsFreeDests) cupsLib.resolve("cupsFreeDests");
  88. _cupsGetPPD = (CupsGetPPD) cupsLib.resolve("cupsGetPPD");
  89. _cupsLangGet = (CupsLangGet) cupsLib.resolve("cupsLangGet");
  90. _cupsLangEncoding = (CupsLangEncoding) cupsLib.resolve("cupsLangEncoding");
  91. _ppdOpenFile = (PPDOpenFile) cupsLib.resolve("ppdOpenFile");
  92. _ppdMarkDefaults = (PPDMarkDefaults) cupsLib.resolve("ppdMarkDefaults");
  93. _ppdClose = (PPDClose) cupsLib.resolve("ppdClose");
  94. _cupsMarkOptions = (CupsMarkOptions) cupsLib.resolve("cupsMarkOptions");
  95. _ppdMarkOption = (PPDMarkOption) cupsLib.resolve("ppdMarkOption");
  96. _cupsFreeOptions = (CupsFreeOptions) cupsLib.resolve("cupsFreeOptions");
  97. _cupsSetDests = (CupsSetDests) cupsLib.resolve("cupsSetDests");
  98. _cupsAddOption = (CupsAddOption) cupsLib.resolve("cupsAddOption");
  99. _cupsTempFd = (CupsTempFd) cupsLib.resolve("cupsTempFd");
  100. _cupsPrintFile = (CupsPrintFile) cupsLib.resolve("cupsPrintFile");
  101. if (_cupsGetDests && _cupsFreeDests) {
  102. cups_dest_t *printers;
  103. int num_printers = _cupsGetDests(&printers);
  104. if (num_printers)
  105. _cupsFreeDests(num_printers, printers);
  106. qt_cups_num_printers = num_printers;
  107. }
  108. }
  109. cupsLoaded = true;
  110. }
  111. // ================ CUPS Support class ========================
  112. QCUPSSupport::QCUPSSupport()
  113. :
  114. prnCount(0),
  115. printers(0),
  116. page_sizes(0),
  117. currPrinterIndex(0),
  118. currPPD(0)
  119. {
  120. if (!cupsLoaded)
  121. resolveCups();
  122. // getting all available printers
  123. if (!isAvailable())
  124. return;
  125. prnCount = _cupsGetDests(&printers);
  126. for (int i = 0; i < prnCount; ++i) {
  127. if (printers[i].is_default) {
  128. currPrinterIndex = i;
  129. setCurrentPrinter(i);
  130. break;
  131. }
  132. }
  133. #ifndef QT_NO_TEXTCODEC
  134. cups_lang_t *cupsLang = _cupsLangGet(0);
  135. codec = QTextCodec::codecForName(_cupsLangEncoding(cupsLang));
  136. if (!codec)
  137. codec = QTextCodec::codecForLocale();
  138. #endif
  139. }
  140. QCUPSSupport::~QCUPSSupport()
  141. {
  142. if (currPPD)
  143. _ppdClose(currPPD);
  144. if (prnCount)
  145. _cupsFreeDests(prnCount, printers);
  146. }
  147. int QCUPSSupport::availablePrintersCount() const
  148. {
  149. return prnCount;
  150. }
  151. const cups_dest_t* QCUPSSupport::availablePrinters() const
  152. {
  153. return printers;
  154. }
  155. const ppd_file_t* QCUPSSupport::currentPPD() const
  156. {
  157. return currPPD;
  158. }
  159. const ppd_file_t* QCUPSSupport::setCurrentPrinter(int index)
  160. {
  161. Q_ASSERT(index >= 0 && index <= prnCount);
  162. if (index == prnCount)
  163. return 0;
  164. currPrinterIndex = index;
  165. if (currPPD)
  166. _ppdClose(currPPD);
  167. currPPD = 0;
  168. page_sizes = 0;
  169. const char *ppdFile = _cupsGetPPD(printers[index].name);
  170. if (!ppdFile)
  171. return 0;
  172. currPPD = _ppdOpenFile(ppdFile);
  173. unlink(ppdFile);
  174. // marking default options
  175. _ppdMarkDefaults(currPPD);
  176. // marking options explicitly set
  177. _cupsMarkOptions(currPPD, printers[currPrinterIndex].num_options, printers[currPrinterIndex].options);
  178. // getting pointer to page sizes
  179. page_sizes = ppdOption("PageSize");
  180. return currPPD;
  181. }
  182. int QCUPSSupport::currentPrinterIndex() const
  183. {
  184. return currPrinterIndex;
  185. }
  186. bool QCUPSSupport::isAvailable()
  187. {
  188. if(!cupsLoaded)
  189. resolveCups();
  190. return _cupsGetDests &&
  191. _cupsFreeDests &&
  192. _cupsGetPPD &&
  193. _ppdOpenFile &&
  194. _ppdMarkDefaults &&
  195. _ppdClose &&
  196. _cupsMarkOptions &&
  197. _ppdMarkOption &&
  198. _cupsFreeOptions &&
  199. _cupsSetDests &&
  200. _cupsLangGet &&
  201. _cupsLangEncoding &&
  202. _cupsAddOption &&
  203. (qt_cups_num_printers > 0);
  204. }
  205. const ppd_option_t* QCUPSSupport::ppdOption(const char *key) const
  206. {
  207. if (currPPD) {
  208. for (int gr = 0; gr < currPPD->num_groups; ++gr) {
  209. for (int opt = 0; opt < currPPD->groups[gr].num_options; ++opt) {
  210. if (qstrcmp(currPPD->groups[gr].options[opt].keyword, key) == 0)
  211. return &currPPD->groups[gr].options[opt];
  212. }
  213. }
  214. }
  215. return 0;
  216. }
  217. const cups_option_t* QCUPSSupport::printerOption(const QString &key) const
  218. {
  219. for (int i = 0; i < printers[currPrinterIndex].num_options; ++i) {
  220. if (QLatin1String(printers[currPrinterIndex].options[i].name) == key)
  221. return &printers[currPrinterIndex].options[i];
  222. }
  223. return 0;
  224. }
  225. const ppd_option_t* QCUPSSupport::pageSizes() const
  226. {
  227. return page_sizes;
  228. }
  229. int QCUPSSupport::markOption(const char* name, const char* value)
  230. {
  231. return _ppdMarkOption(currPPD, name, value);
  232. }
  233. void QCUPSSupport::saveOptions(QList<const ppd_option_t*> options, QList<const char*> markedOptions)
  234. {
  235. int oldOptionCount = printers[currPrinterIndex].num_options;
  236. cups_option_t* oldOptions = printers[currPrinterIndex].options;
  237. int newOptionCount = 0;
  238. cups_option_t* newOptions = 0;
  239. // copying old options that are not on the new list
  240. for (int i = 0; i < oldOptionCount; ++i) {
  241. bool contains = false;
  242. for (int j = 0; j < options.count(); ++j) {
  243. if (qstrcmp(options.at(j)->keyword, oldOptions[i].name) == 0) {
  244. contains = true;
  245. break;
  246. }
  247. }
  248. if (!contains) {
  249. newOptionCount = _cupsAddOption(oldOptions[i].name, oldOptions[i].value, newOptionCount, &newOptions);
  250. }
  251. }
  252. // we can release old option list
  253. _cupsFreeOptions(oldOptionCount, oldOptions);
  254. // adding marked options
  255. for (int i = 0; i < markedOptions.count(); ++i) {
  256. const char* name = markedOptions.at(i);
  257. ++i;
  258. newOptionCount = _cupsAddOption(name, markedOptions.at(i), newOptionCount, &newOptions);
  259. }
  260. // placing the new option list
  261. printers[currPrinterIndex].num_options = newOptionCount;
  262. printers[currPrinterIndex].options = newOptions;
  263. // saving new default values
  264. _cupsSetDests(prnCount, printers);
  265. }
  266. QRect QCUPSSupport::paperRect(const char *choice) const
  267. {
  268. if (!currPPD)
  269. return QRect();
  270. for (int i = 0; i < currPPD->num_sizes; ++i) {
  271. if (qstrcmp(currPPD->sizes[i].name, choice) == 0)
  272. return QRect(0, 0, qRound(currPPD->sizes[i].width), qRound(currPPD->sizes[i].length));
  273. }
  274. return QRect();
  275. }
  276. QRect QCUPSSupport::pageRect(const char *choice) const
  277. {
  278. if (!currPPD)
  279. return QRect();
  280. for (int i = 0; i < currPPD->num_sizes; ++i) {
  281. if (qstrcmp(currPPD->sizes[i].name, choice) == 0)
  282. return QRect(qRound(currPPD->sizes[i].left),
  283. qRound(currPPD->sizes[i].length - currPPD->sizes[i].top),
  284. qRound(currPPD->sizes[i].right - currPPD->sizes[i].left),
  285. qRound(currPPD->sizes[i].top - currPPD->sizes[i].bottom));
  286. }
  287. return QRect();
  288. }
  289. QStringList QCUPSSupport::options() const
  290. {
  291. QStringList list;
  292. collectMarkedOptions(list);
  293. return list;
  294. }
  295. bool QCUPSSupport::printerHasPPD(const char *printerName)
  296. {
  297. if (!isAvailable())
  298. return false;
  299. return _cupsGetPPD(printerName) != 0;
  300. }
  301. QString QCUPSSupport::unicodeString(const char *s)
  302. {
  303. #ifndef QT_NO_TEXTCODEC
  304. return codec->toUnicode(s);
  305. #else
  306. return QLatin1String(s);
  307. #endif
  308. }
  309. void QCUPSSupport::collectMarkedOptions(QStringList& list, const ppd_group_t* group) const
  310. {
  311. if (group == 0) {
  312. if (!currPPD)
  313. return;
  314. for (int i = 0; i < currPPD->num_groups; ++i) {
  315. collectMarkedOptions(list, &currPPD->groups[i]);
  316. collectMarkedOptionsHelper(list, &currPPD->groups[i]);
  317. }
  318. } else {
  319. for (int i = 0; i < group->num_subgroups; ++i)
  320. collectMarkedOptionsHelper(list, &group->subgroups[i]);
  321. }
  322. }
  323. void QCUPSSupport::collectMarkedOptionsHelper(QStringList& list, const ppd_group_t* group) const
  324. {
  325. for (int i = 0; i < group->num_options; ++i) {
  326. for (int j = 0; j < group->options[i].num_choices; ++j) {
  327. if (group->options[i].choices[j].marked == 1 && qstrcmp(group->options[i].choices[j].choice, group->options[i].defchoice) != 0)
  328. list << QString::fromLocal8Bit(group->options[i].keyword) << QString::fromLocal8Bit(group->options[i].choices[j].choice);
  329. }
  330. }
  331. }
  332. QPair<int, QString> QCUPSSupport::tempFd()
  333. {
  334. char filename[512];
  335. int fd = _cupsTempFd(filename, 512);
  336. return QPair<int, QString>(fd, QString::fromLocal8Bit(filename));
  337. }
  338. // Prints the given file and returns a job id.
  339. int QCUPSSupport::printFile(const char * printerName, const char * filename, const char * title,
  340. int num_options, cups_option_t * options)
  341. {
  342. return _cupsPrintFile(printerName, filename, title, num_options, options);
  343. }
  344. QT_END_NAMESPACE
  345. #endif // QT_NO_CUPS