source: trunk/src/gui/painting/qprinterinfo_unix.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 38.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this 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 have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qprinterinfo.h"
43
44#include <qfile.h>
45#include <qfileinfo.h>
46#include <qdir.h>
47#include <qprintdialog.h>
48#include <qlibrary.h>
49#include <qtextstream.h>
50
51#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
52# include <private/qcups_p.h>
53# include <cups/cups.h>
54# include <private/qpdf_p.h>
55#endif
56
57#include <private/qprinterinfo_unix_p.h>
58
59QT_BEGIN_NAMESPACE
60
61#ifndef QT_NO_PRINTER
62
63class QPrinterInfoPrivate
64{
65Q_DECLARE_PUBLIC(QPrinterInfo)
66public:
67 QPrinterInfoPrivate();
68 QPrinterInfoPrivate(const QString& name);
69 ~QPrinterInfoPrivate();
70
71 static QPrinter::PaperSize string2PaperSize(const QString& str);
72 static QString pageSize2String(QPrinter::PaperSize size);
73
74private:
75 QString m_name;
76 bool m_isNull;
77 bool m_default;
78 mutable bool m_mustGetPaperSizes;
79 mutable QList<QPrinter::PaperSize> m_paperSizes;
80 int m_cupsPrinterIndex;
81
82 QPrinterInfo* q_ptr;
83};
84
85static QPrinterInfoPrivate nullQPrinterInfoPrivate;
86
87class QPrinterInfoPrivateDeleter
88{
89public:
90 static inline void cleanup(QPrinterInfoPrivate *d)
91 {
92 if (d != &nullQPrinterInfoPrivate)
93 delete d;
94 }
95};
96
97/////////////////////////////////////////////////////////////////////////////
98/////////////////////////////////////////////////////////////////////////////
99
100void qt_perhapsAddPrinter(QList<QPrinterDescription> *printers, const QString &name,
101 QString host, QString comment,
102 QStringList aliases)
103{
104 for (int i = 0; i < printers->size(); ++i)
105 if (printers->at(i).samePrinter(name))
106 return;
107
108#ifndef QT_NO_PRINTDIALOG
109 if (host.isEmpty())
110 host = QPrintDialog::tr("locally connected");
111#endif
112 printers->append(QPrinterDescription(name.simplified(), host.simplified(), comment.simplified(), aliases));
113}
114
115void qt_parsePrinterDesc(QString printerDesc, QList<QPrinterDescription> *printers)
116{
117 if (printerDesc.length() < 1)
118 return;
119
120 printerDesc = printerDesc.simplified();
121 int i = printerDesc.indexOf(QLatin1Char(':'));
122 QString printerName, printerComment, printerHost;
123 QStringList aliases;
124
125 if (i >= 0) {
126 // have ':' want '|'
127 int j = printerDesc.indexOf(QLatin1Char('|'));
128 if (j > 0 && j < i) {
129 printerName = printerDesc.left(j);
130 aliases = printerDesc.mid(j + 1, i - j - 1).split(QLatin1Char('|'));
131#ifndef QT_NO_PRINTDIALOG
132 // try extracting a comment from the aliases
133 printerComment = QPrintDialog::tr("Aliases: %1")
134 .arg(aliases.join(QLatin1String(", ")));
135#endif
136 } else {
137 printerName = printerDesc.left(i);
138 }
139 // look for lprng pseudo all printers entry
140 i = printerDesc.indexOf(QRegExp(QLatin1String(": *all *=")));
141 if (i >= 0)
142 printerName = QString();
143 // look for signs of this being a remote printer
144 i = printerDesc.indexOf(QRegExp(QLatin1String(": *rm *=")));
145 if (i >= 0) {
146 // point k at the end of remote host name
147 while (printerDesc[i] != QLatin1Char('='))
148 i++;
149 while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace())
150 i++;
151 j = i;
152 while (j < (int)printerDesc.length() && printerDesc[j] != QLatin1Char(':'))
153 j++;
154
155 // and stuff that into the string
156 printerHost = printerDesc.mid(i, j - i);
157 }
158 }
159 if (printerName.length())
160 qt_perhapsAddPrinter(printers, printerName, printerHost, printerComment,
161 aliases);
162}
163
164int qt_parsePrintcap(QList<QPrinterDescription> *printers, const QString& fileName)
165{
166 QFile printcap(fileName);
167 if (!printcap.open(QIODevice::ReadOnly))
168 return NotFound;
169
170 char *line_ascii = new char[1025];
171 line_ascii[1024] = '\0';
172
173 QString printerDesc;
174 bool atEnd = false;
175
176 while (!atEnd) {
177 if (printcap.atEnd() || printcap.readLine(line_ascii, 1024) <= 0)
178 atEnd = true;
179 QString line = QString::fromLocal8Bit(line_ascii);
180 line = line.trimmed();
181 if (line.length() >= 1 && line[int(line.length()) - 1] == QLatin1Char('\\'))
182 line.chop(1);
183 if (line[0] == QLatin1Char('#')) {
184 if (!atEnd)
185 continue;
186 } else if (line[0] == QLatin1Char('|') || line[0] == QLatin1Char(':')
187 || line.isEmpty()) {
188 printerDesc += line;
189 if (!atEnd)
190 continue;
191 }
192
193 qt_parsePrinterDesc(printerDesc, printers);
194
195 // add the first line of the new printer definition
196 printerDesc = line;
197 }
198 delete[] line_ascii;
199 return Success;
200}
201
202/*!
203 \internal
204
205 Checks $HOME/.printers for a line matching '_default <name>' (where
206 <name> does not contain any white space). The first such match
207 results in <name> being returned.
208 If no lines match then an empty string is returned.
209*/
210QString qt_getDefaultFromHomePrinters()
211{
212 QFile file(QDir::homePath() + QLatin1String("/.printers"));
213 if (!file.open(QIODevice::ReadOnly))
214 return QString();
215 QString all(QLatin1String(file.readAll()));
216 QStringList words = all.split(QRegExp(QLatin1String("\\W+")), QString::SkipEmptyParts);
217 const int i = words.indexOf(QLatin1String("_default"));
218 if (i != -1 && i < words.size() - 1)
219 return words.at(i + 1);
220 return QString();
221}
222
223// solaris, not 2.6
224void qt_parseEtcLpPrinters(QList<QPrinterDescription> *printers)
225{
226 QDir lp(QLatin1String("/etc/lp/printers"));
227 QFileInfoList dirs = lp.entryInfoList();
228 if (dirs.isEmpty())
229 return;
230
231 QString tmp;
232 for (int i = 0; i < dirs.size(); ++i) {
233 QFileInfo printer = dirs.at(i);
234 if (printer.isDir()) {
235 tmp.sprintf("/etc/lp/printers/%s/configuration",
236 printer.fileName().toAscii().data());
237 QFile configuration(tmp);
238 char *line = new char[1025];
239 QString remote(QLatin1String("Remote:"));
240 QString contentType(QLatin1String("Content types:"));
241 QString printerHost;
242 bool canPrintPostscript = false;
243 if (configuration.open(QIODevice::ReadOnly)) {
244 while (!configuration.atEnd() &&
245 configuration.readLine(line, 1024) > 0) {
246 if (QString::fromLatin1(line).startsWith(remote)) {
247 const char *p = line;
248 while (*p != ':')
249 p++;
250 p++;
251 while (isspace((uchar) *p))
252 p++;
253 printerHost = QString::fromLocal8Bit(p);
254 printerHost = printerHost.simplified();
255 } else if (QString::fromLatin1(line).startsWith(contentType)) {
256 char *p = line;
257 while (*p != ':')
258 p++;
259 p++;
260 char *e;
261 while (*p) {
262 while (isspace((uchar) *p))
263 p++;
264 if (*p) {
265 char s;
266 e = p;
267 while (isalnum((uchar) *e))
268 e++;
269 s = *e;
270 *e = '\0';
271 if (!qstrcmp(p, "postscript") ||
272 !qstrcmp(p, "any"))
273 canPrintPostscript = true;
274 *e = s;
275 if (s == ',')
276 e++;
277 p = e;
278 }
279 }
280 }
281 }
282 if (canPrintPostscript)
283 qt_perhapsAddPrinter(printers, printer.fileName(),
284 printerHost, QLatin1String(""));
285 }
286 delete[] line;
287 }
288 }
289}
290
291// solaris 2.6
292char *qt_parsePrintersConf(QList<QPrinterDescription> *printers, bool *found)
293{
294 QFile pc(QLatin1String("/etc/printers.conf"));
295 if (!pc.open(QIODevice::ReadOnly)) {
296 if (found)
297 *found = false;
298 return 0;
299 }
300 if (found)
301 *found = true;
302
303 char *line = new char[1025];
304 line[1024] = '\0';
305
306 QString printerDesc;
307 int lineLength = 0;
308
309 char *defaultPrinter = 0;
310
311 while (!pc.atEnd() &&
312 (lineLength=pc.readLine(line, 1024)) > 0) {
313 if (*line == '#') {
314 *line = '\0';
315 lineLength = 0;
316 }
317 if (lineLength >= 2 && line[lineLength-2] == '\\') {
318 line[lineLength-2] = '\0';
319 printerDesc += QString::fromLocal8Bit(line);
320 } else {
321 printerDesc += QString::fromLocal8Bit(line);
322 printerDesc = printerDesc.simplified();
323 int i = printerDesc.indexOf(QLatin1Char(':'));
324 QString printerName, printerHost, printerComment;
325 QStringList aliases;
326 if (i >= 0) {
327 // have : want |
328 int j = printerDesc.indexOf(QLatin1Char('|'));
329 if (j >= i)
330 j = -1;
331 printerName = printerDesc.mid(0, j < 0 ? i : j);
332 if (printerName == QLatin1String("_default")) {
333 i = printerDesc.indexOf(
334 QRegExp(QLatin1String(": *use *=")));
335 while (printerDesc[i] != QLatin1Char('='))
336 i++;
337 while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace())
338 i++;
339 j = i;
340 while (j < (int)printerDesc.length() &&
341 printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(','))
342 j++;
343 // that's our default printer
344 defaultPrinter =
345 qstrdup(printerDesc.mid(i, j-i).toAscii().data());
346 printerName = QString();
347 printerDesc = QString();
348 } else if (printerName == QLatin1String("_all")) {
349 // skip it.. any other cases we want to skip?
350 printerName = QString();
351 printerDesc = QString();
352 }
353
354 if (j > 0) {
355 // try extracting a comment from the aliases
356 aliases = printerDesc.mid(j + 1, i - j - 1).split(QLatin1Char('|'));
357#ifndef QT_NO_PRINTDIALOG
358 printerComment = QPrintDialog::tr("Aliases: %1")
359 .arg(aliases.join(QLatin1String(", ")));
360#endif
361 }
362 // look for signs of this being a remote printer
363 i = printerDesc.indexOf(
364 QRegExp(QLatin1String(": *bsdaddr *=")));
365 if (i >= 0) {
366 // point k at the end of remote host name
367 while (printerDesc[i] != QLatin1Char('='))
368 i++;
369 while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace())
370 i++;
371 j = i;
372 while (j < (int)printerDesc.length() &&
373 printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(','))
374 j++;
375 // and stuff that into the string
376 printerHost = printerDesc.mid(i, j-i);
377 // maybe stick the remote printer name into the comment
378 if (printerDesc[j] == QLatin1Char(',')) {
379 i = ++j;
380 while (printerDesc[i].isSpace())
381 i++;
382 j = i;
383 while (j < (int)printerDesc.length() &&
384 printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(','))
385 j++;
386 if (printerName != printerDesc.mid(i, j-i)) {
387 printerComment =
388 QLatin1String("Remote name: ");
389 printerComment += printerDesc.mid(i, j-i);
390 }
391 }
392 }
393 }
394 if (printerComment == QLatin1String(":"))
395 printerComment = QString(); // for cups
396 if (printerName.length())
397 qt_perhapsAddPrinter(printers, printerName, printerHost,
398 printerComment, aliases);
399 // chop away the line, for processing the next one
400 printerDesc = QString();
401 }
402 }
403 delete[] line;
404 return defaultPrinter;
405}
406
407#ifndef QT_NO_NIS
408
409#if defined(Q_C_CALLBACKS)
410extern "C" {
411#endif
412
413int qt_pd_foreach(int /*status */, char * /*key */, int /*keyLen */,
414 char *val, int valLen, char *data)
415{
416 qt_parsePrinterDesc(QString::fromLatin1(val, valLen), (QList<QPrinterDescription> *)data);
417 return 0;
418}
419
420#if defined(Q_C_CALLBACKS)
421}
422#endif
423
424int qt_retrieveNisPrinters(QList<QPrinterDescription> *printers)
425{
426#ifndef QT_NO_LIBRARY
427 typedef int (*WildCast)(int, char *, int, char *, int, char *);
428 char printersConfByname[] = "printers.conf.byname";
429 char *domain;
430 int err;
431
432 QLibrary lib(QLatin1String("nsl"));
433 typedef int (*ypGetDefaultDomain)(char **);
434 ypGetDefaultDomain _ypGetDefaultDomain = (ypGetDefaultDomain)lib.resolve("yp_get_default_domain");
435 typedef int (*ypAll)(const char *, const char *, const struct ypall_callback *);
436 ypAll _ypAll = (ypAll)lib.resolve("yp_all");
437
438 if (_ypGetDefaultDomain && _ypAll) {
439 err = _ypGetDefaultDomain(&domain);
440 if (err == 0) {
441 ypall_callback cb;
442 // wild cast to support K&R-style system headers
443 (WildCast &) cb.foreach = (WildCast) qt_pd_foreach;
444 cb.data = (char *) printers;
445 err = _ypAll(domain, printersConfByname, &cb);
446 }
447 if (!err)
448 return Success;
449 }
450#endif //QT_NO_LIBRARY
451 return Unavail;
452}
453
454#endif // QT_NO_NIS
455
456char *qt_parseNsswitchPrintersEntry(QList<QPrinterDescription> *printers, char *line)
457{
458#define skipSpaces() \
459 while (line[k] != '\0' && isspace((uchar) line[k])) \
460 k++
461
462 char *defaultPrinter = 0;
463 bool stop = false;
464 int lastStatus = NotFound;
465
466 int k = 8;
467 skipSpaces();
468 if (line[k] != ':')
469 return 0;
470 k++;
471
472 char *cp = strchr(line, '#');
473 if (cp != 0)
474 *cp = '\0';
475
476 while (line[k] != '\0') {
477 if (isspace((uchar) line[k])) {
478 k++;
479 } else if (line[k] == '[') {
480 k++;
481 skipSpaces();
482 while (line[k] != '\0') {
483 char status = tolower(line[k]);
484 char action = '?';
485
486 while (line[k] != '=' && line[k] != ']' && line[k] != '\0')
487 k++;
488 if (line[k] == '=') {
489 k++;
490 skipSpaces();
491 action = tolower(line[k]);
492 while (line[k] != '\0' && !isspace((uchar) line[k]) && line[k] != ']')
493 k++;
494 } else if (line[k] == ']') {
495 k++;
496 break;
497 }
498 skipSpaces();
499
500 if (lastStatus == status)
501 stop = (action == (char) Return);
502 }
503 } else {
504 if (stop)
505 break;
506
507 QByteArray source;
508 while (line[k] != '\0' && !isspace((uchar) line[k]) && line[k] != '[') {
509 source += line[k];
510 k++;
511 }
512
513 if (source == "user") {
514 lastStatus = qt_parsePrintcap(printers,
515 QDir::homePath() + QLatin1String("/.printers"));
516 } else if (source == "files") {
517 bool found;
518 defaultPrinter = qt_parsePrintersConf(printers, &found);
519 if (found)
520 lastStatus = Success;
521#ifndef QT_NO_NIS
522 } else if (source == "nis") {
523 lastStatus = qt_retrieveNisPrinters(printers);
524#endif
525 } else {
526 // nisplus, dns, etc., are not implemented yet
527 lastStatus = NotFound;
528 }
529 stop = (lastStatus == Success);
530 }
531 }
532 return defaultPrinter;
533}
534
535char *qt_parseNsswitchConf(QList<QPrinterDescription> *printers)
536{
537 QFile nc(QLatin1String("/etc/nsswitch.conf"));
538 if (!nc.open(QIODevice::ReadOnly))
539 return 0;
540
541 char *defaultPrinter = 0;
542
543 char *line = new char[1025];
544 line[1024] = '\0';
545
546 while (!nc.atEnd() &&
547 nc.readLine(line, 1024) > 0) {
548 if (qstrncmp(line, "printers", 8) == 0) {
549 defaultPrinter = qt_parseNsswitchPrintersEntry(printers, line);
550 delete[] line;
551 return defaultPrinter;
552 }
553 }
554
555 strcpy(line, "printers: user files nis nisplus xfn");
556 defaultPrinter = qt_parseNsswitchPrintersEntry(printers, line);
557 delete[] line;
558 return defaultPrinter;
559}
560
561// HP-UX
562void qt_parseEtcLpMember(QList<QPrinterDescription> *printers)
563{
564 QDir lp(QLatin1String("/etc/lp/member"));
565 if (!lp.exists())
566 return;
567 QFileInfoList dirs = lp.entryInfoList();
568 if (dirs.isEmpty())
569 return;
570
571#ifdef QT_NO_PRINTDIALOG
572 Q_UNUSED(printers);
573#else
574 QString tmp;
575 for (int i = 0; i < dirs.size(); ++i) {
576 QFileInfo printer = dirs.at(i);
577 // I haven't found any real documentation, so I'm guessing that
578 // since lpstat uses /etc/lp/member rather than one of the
579 // other directories, it's the one to use. I did not find a
580 // decent way to locate aliases and remote printers.
581 if (printer.isFile())
582 qt_perhapsAddPrinter(printers, printer.fileName(),
583 QPrintDialog::tr("unknown"),
584 QLatin1String(""));
585 }
586#endif
587}
588
589// IRIX 6.x
590void qt_parseSpoolInterface(QList<QPrinterDescription> *printers)
591{
592 QDir lp(QLatin1String("/usr/spool/lp/interface"));
593 if (!lp.exists())
594 return;
595 QFileInfoList files = lp.entryInfoList();
596 if(files.isEmpty())
597 return;
598
599 for (int i = 0; i < files.size(); ++i) {
600 QFileInfo printer = files.at(i);
601
602 if (!printer.isFile())
603 continue;
604
605 // parse out some information
606 QFile configFile(printer.filePath());
607 if (!configFile.open(QIODevice::ReadOnly))
608 continue;
609
610 QByteArray line;
611 line.resize(1025);
612 QString namePrinter;
613 QString hostName;
614 QString hostPrinter;
615 QString printerType;
616
617 QString nameKey(QLatin1String("NAME="));
618 QString typeKey(QLatin1String("TYPE="));
619 QString hostKey(QLatin1String("HOSTNAME="));
620 QString hostPrinterKey(QLatin1String("HOSTPRINTER="));
621
622 while (!configFile.atEnd() &&
623 (configFile.readLine(line.data(), 1024)) > 0) {
624 QString uline = QString::fromLocal8Bit(line);
625 if (uline.startsWith(typeKey) ) {
626 printerType = uline.mid(nameKey.length());
627 printerType = printerType.simplified();
628 } else if (uline.startsWith(hostKey)) {
629 hostName = uline.mid(hostKey.length());
630 hostName = hostName.simplified();
631 } else if (uline.startsWith(hostPrinterKey)) {
632 hostPrinter = uline.mid(hostPrinterKey.length());
633 hostPrinter = hostPrinter.simplified();
634 } else if (uline.startsWith(nameKey)) {
635 namePrinter = uline.mid(nameKey.length());
636 namePrinter = namePrinter.simplified();
637 }
638 }
639 configFile.close();
640
641 printerType = printerType.trimmed();
642 if (printerType.indexOf(QLatin1String("postscript"), 0, Qt::CaseInsensitive) < 0)
643 continue;
644
645 int ii = 0;
646 while ((ii = namePrinter.indexOf(QLatin1Char('"'), ii)) >= 0)
647 namePrinter.remove(ii, 1);
648
649 if (hostName.isEmpty() || hostPrinter.isEmpty()) {
650 qt_perhapsAddPrinter(printers, printer.fileName(),
651 QLatin1String(""), namePrinter);
652 } else {
653 QString comment;
654 comment = namePrinter;
655 comment += QLatin1String(" (");
656 comment += hostPrinter;
657 comment += QLatin1Char(')');
658 qt_perhapsAddPrinter(printers, printer.fileName(),
659 hostName, comment);
660 }
661 }
662}
663
664
665// Every unix must have its own. It's a standard. Here is AIX.
666void qt_parseQconfig(QList<QPrinterDescription> *printers)
667{
668 QFile qconfig(QLatin1String("/etc/qconfig"));
669 if (!qconfig.open(QIODevice::ReadOnly))
670 return;
671
672 QTextStream ts(&qconfig);
673 QString line;
674
675 QString stanzaName; // either a queue or a device name
676 bool up = true; // queue up? default true, can be false
677 QString remoteHost; // null if local
678 QString deviceName; // null if remote
679
680 QRegExp newStanza(QLatin1String("^[0-z\\-]*:$"));
681
682 // our basic strategy here is to process each line, detecting new
683 // stanzas. each time we see a new stanza, we check if the
684 // previous stanza was a valid queue for a) a remote printer or b)
685 // a local printer. if it wasn't, we assume that what we see is
686 // the start of the first stanza, or that the previous stanza was
687 // a device stanza, or that there is some syntax error (we don't
688 // report those).
689
690 do {
691 line = ts.readLine();
692 bool indented = line[0].isSpace();
693 line = line.simplified();
694
695 int i = line.indexOf(QLatin1Char('='));
696 if (indented && i != -1) { // line in stanza
697 QString variable = line.left(i).simplified();
698 QString value=line.mid(i+1, line.length()).simplified();
699 if (variable == QLatin1String("device"))
700 deviceName = value;
701 else if (variable == QLatin1String("host"))
702 remoteHost = value;
703 else if (variable == QLatin1String("up"))
704 up = !(value.toLower() == QLatin1String("false"));
705 } else if (line[0] == QLatin1Char('*')) { // comment
706 // nothing to do
707 } else if (ts.atEnd() || // end of file, or beginning of new stanza
708 (!indented && line.contains(newStanza))) {
709 if (up && stanzaName.length() > 0 && stanzaName.length() < 21) {
710 if (remoteHost.length()) // remote printer
711 qt_perhapsAddPrinter(printers, stanzaName, remoteHost,
712 QString());
713 else if (deviceName.length()) // local printer
714 qt_perhapsAddPrinter(printers, stanzaName, QString(),
715 QString());
716 }
717 line.chop(1);
718 if (line.length() >= 1 && line.length() <= 20)
719 stanzaName = line;
720 up = true;
721 remoteHost.clear();
722 deviceName.clear();
723 } else {
724 // syntax error? ignore.
725 }
726 } while (!ts.atEnd());
727}
728
729#ifndef QT_NO_LPR
730int qt_getLprPrinters(QList<QPrinterDescription>& printers)
731{
732 QByteArray etcLpDefault;
733 qt_parsePrintcap(&printers, QLatin1String("/etc/printcap"));
734 qt_parseEtcLpMember(&printers);
735 qt_parseSpoolInterface(&printers);
736 qt_parseQconfig(&printers);
737
738 QFileInfo f;
739 f.setFile(QLatin1String("/etc/lp/printers"));
740 if (f.isDir()) {
741 qt_parseEtcLpPrinters(&printers);
742 QFile def(QLatin1String("/etc/lp/default"));
743 if (def.open(QIODevice::ReadOnly)) {
744 etcLpDefault.resize(1025);
745 if (def.readLine(etcLpDefault.data(), 1024) > 0) {
746 QRegExp rx(QLatin1String("^(\\S+)"));
747 if (rx.indexIn(QString::fromLatin1(etcLpDefault)) != -1)
748 etcLpDefault = rx.cap(1).toAscii();
749 }
750 }
751 }
752
753 char *def = 0;
754 f.setFile(QLatin1String("/etc/nsswitch.conf"));
755 if (f.isFile()) {
756 def = qt_parseNsswitchConf(&printers);
757 } else {
758 f.setFile(QLatin1String("/etc/printers.conf"));
759 if (f.isFile())
760 def = qt_parsePrintersConf(&printers);
761 }
762
763 if (def) {
764 etcLpDefault = def;
765 delete [] def;
766 }
767
768 QString homePrintersDefault = qt_getDefaultFromHomePrinters();
769
770 // all printers hopefully known. try to find a good default
771 QString dollarPrinter;
772 {
773 dollarPrinter = QString::fromLocal8Bit(qgetenv("PRINTER"));
774 if (dollarPrinter.isEmpty())
775 dollarPrinter = QString::fromLocal8Bit(qgetenv("LPDEST"));
776 if (dollarPrinter.isEmpty())
777 dollarPrinter = QString::fromLocal8Bit(qgetenv("NPRINTER"));
778 if (dollarPrinter.isEmpty())
779 dollarPrinter = QString::fromLocal8Bit(qgetenv("NGPRINTER"));
780#ifndef QT_NO_PRINTDIALOG
781 if (!dollarPrinter.isEmpty())
782 qt_perhapsAddPrinter(&printers, dollarPrinter,
783 QPrintDialog::tr("unknown"),
784 QLatin1String(""));
785#endif
786 }
787
788 int quality = 0;
789 int best = 0;
790 for (int i = 0; i < printers.size(); ++i) {
791 QRegExp ps(QLatin1String("[^a-z]ps(?:[^a-z]|$)"));
792 QRegExp lp(QLatin1String("[^a-z]lp(?:[^a-z]|$)"));
793
794 QString name = printers.at(i).name;
795 QString comment = printers.at(i).comment;
796 if (quality < 5 && name == dollarPrinter) {
797 best = i;
798 quality = 5;
799 } else if (quality < 4 && !homePrintersDefault.isEmpty() &&
800 name == homePrintersDefault) {
801 best = i;
802 quality = 4;
803 } else if (quality < 3 && !etcLpDefault.isEmpty() &&
804 name == QLatin1String(etcLpDefault)) {
805 best = i;
806 quality = 3;
807 } else if (quality < 2 &&
808 (name == QLatin1String("ps") ||
809 ps.indexIn(comment) != -1)) {
810 best = i;
811 quality = 2;
812 } else if (quality < 1 &&
813 (name == QLatin1String("lp") ||
814 lp.indexIn(comment) > -1)) {
815 best = i;
816 quality = 1;
817 }
818 }
819
820 return best;
821}
822#endif
823
824/////////////////////////////////////////////////////////////////////////////
825/////////////////////////////////////////////////////////////////////////////
826
827QList<QPrinterInfo> QPrinterInfo::availablePrinters()
828{
829 QList<QPrinterInfo> list;
830
831#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
832 QCUPSSupport cups;
833 if (QCUPSSupport::isAvailable()) {
834 //const ppd_file_t* cupsPPD = cups.currentPPD();
835 int cupsPrinterCount = cups.availablePrintersCount();
836 const cups_dest_t* cupsPrinters = cups.availablePrinters();
837
838 for (int i = 0; i < cupsPrinterCount; ++i) {
839 QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
840 if (cupsPrinters[i].instance)
841 printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
842 list.append(QPrinterInfo(printerName));
843 if (cupsPrinters[i].is_default)
844 list[i].d_ptr->m_default = true;
845 list[i].d_ptr->m_cupsPrinterIndex = i;
846 }
847 } else {
848#endif
849 QList<QPrinterDescription> lprPrinters;
850 int defprn = qt_getLprPrinters(lprPrinters);
851 // populating printer combo
852 QList<QPrinterDescription>::const_iterator i = lprPrinters.constBegin();
853 for(; i != lprPrinters.constEnd(); ++i) {
854 list.append(QPrinterInfo((*i).name));
855 }
856 if (defprn >= 0 && defprn < lprPrinters.size()) {
857 list[defprn].d_ptr->m_default = true;
858 }
859#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
860 }
861#endif
862
863 return list;
864}
865
866QPrinterInfo QPrinterInfo::defaultPrinter()
867{
868 QList<QPrinterInfo> prnList = availablePrinters();
869 for (int i = 0; i < prnList.size(); ++i) {
870 if (prnList[i].isDefault())
871 return prnList[i];
872 }
873 return (prnList.size() > 0) ? prnList[0] : QPrinterInfo();
874}
875
876QPrinterInfo::QPrinterInfo()
877 : d_ptr(&nullQPrinterInfoPrivate)
878{
879}
880
881QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
882 : d_ptr(&nullQPrinterInfoPrivate)
883{
884 *this = src;
885}
886
887QPrinterInfo::QPrinterInfo(const QPrinter& printer)
888 : d_ptr(new QPrinterInfoPrivate(printer.printerName()))
889{
890
891 Q_D(QPrinterInfo);
892 d->q_ptr = this;
893
894#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
895 QCUPSSupport cups;
896 if (QCUPSSupport::isAvailable()) {
897 int cupsPrinterCount = cups.availablePrintersCount();
898 const cups_dest_t* cupsPrinters = cups.availablePrinters();
899
900 for (int i = 0; i < cupsPrinterCount; ++i) {
901 QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
902 if (cupsPrinters[i].instance)
903 printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
904 if (printerName == printer.printerName()) {
905 if (cupsPrinters[i].is_default)
906 d->m_default = true;
907 d->m_cupsPrinterIndex = i;
908 return;
909 }
910 }
911 } else {
912#endif
913 QList<QPrinterDescription> lprPrinters;
914 int defprn = qt_getLprPrinters(lprPrinters);
915 // populating printer combo
916 QList<QPrinterDescription>::const_iterator i = lprPrinters.constBegin();
917 int c;
918 for(c = 0; i != lprPrinters.constEnd(); ++i, ++c) {
919 if (i->name == printer.printerName()) {
920 if (defprn == c)
921 d->m_default = true;
922 return;
923 }
924 }
925#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
926 }
927#endif
928
929 // Printer not found.
930 d_ptr.reset(&nullQPrinterInfoPrivate);
931}
932
933QPrinterInfo::QPrinterInfo(const QString& name)
934 : d_ptr(new QPrinterInfoPrivate(name))
935{
936 d_ptr->q_ptr = this;
937}
938
939QPrinterInfo::~QPrinterInfo()
940{
941}
942
943QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
944{
945 Q_ASSERT(d_ptr);
946 d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
947 d_ptr->q_ptr = this;
948 return *this;
949}
950
951QString QPrinterInfo::printerName() const
952{
953 const Q_D(QPrinterInfo);
954 return d->m_name;
955}
956
957bool QPrinterInfo::isNull() const
958{
959 const Q_D(QPrinterInfo);
960 return d->m_isNull;
961}
962
963bool QPrinterInfo::isDefault() const
964{
965 const Q_D(QPrinterInfo);
966 return d->m_default;
967}
968
969QList< QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
970{
971 const Q_D(QPrinterInfo);
972 if (d->m_mustGetPaperSizes) {
973 d->m_mustGetPaperSizes = false;
974
975#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
976 QCUPSSupport cups;
977 if (QCUPSSupport::isAvailable()) {
978 // Find paper sizes from CUPS.
979 cups.setCurrentPrinter(d->m_cupsPrinterIndex);
980 const ppd_option_t* sizes = cups.pageSizes();
981 if (sizes) {
982 for (int j = 0; j < sizes->num_choices; ++j) {
983 d->m_paperSizes.append(
984 QPrinterInfoPrivate::string2PaperSize(
985 QLatin1String(sizes->choices[j].choice)));
986 }
987 }
988 }
989#endif
990
991 }
992 return d->m_paperSizes;
993}
994
995/////////////////////////////////////////////////////////////////////////////
996/////////////////////////////////////////////////////////////////////////////
997
998QPrinterInfoPrivate::QPrinterInfoPrivate()
999{
1000 m_isNull = true;
1001 m_default = false;
1002 m_mustGetPaperSizes = true;
1003 m_cupsPrinterIndex = 0;
1004 q_ptr = 0;
1005}
1006
1007QPrinterInfoPrivate::QPrinterInfoPrivate(const QString& name)
1008{
1009 m_name = name;
1010 m_isNull = false;
1011 m_default = false;
1012 m_mustGetPaperSizes = true;
1013 m_cupsPrinterIndex = 0;
1014 q_ptr = 0;
1015}
1016
1017QPrinterInfoPrivate::~QPrinterInfoPrivate()
1018{
1019}
1020
1021QPrinter::PaperSize QPrinterInfoPrivate::string2PaperSize(const QString& str)
1022{
1023 if (str == QLatin1String("A4")) {
1024 return QPrinter::A4;
1025 } else if (str == QLatin1String("B5")) {
1026 return QPrinter::B5;
1027 } else if (str == QLatin1String("Letter")) {
1028 return QPrinter::Letter;
1029 } else if (str == QLatin1String("Legal")) {
1030 return QPrinter::Legal;
1031 } else if (str == QLatin1String("Executive")) {
1032 return QPrinter::Executive;
1033 } else if (str == QLatin1String("A0")) {
1034 return QPrinter::A0;
1035 } else if (str == QLatin1String("A1")) {
1036 return QPrinter::A1;
1037 } else if (str == QLatin1String("A2")) {
1038 return QPrinter::A2;
1039 } else if (str == QLatin1String("A3")) {
1040 return QPrinter::A3;
1041 } else if (str == QLatin1String("A5")) {
1042 return QPrinter::A5;
1043 } else if (str == QLatin1String("A6")) {
1044 return QPrinter::A6;
1045 } else if (str == QLatin1String("A7")) {
1046 return QPrinter::A7;
1047 } else if (str == QLatin1String("A8")) {
1048 return QPrinter::A8;
1049 } else if (str == QLatin1String("A9")) {
1050 return QPrinter::A9;
1051 } else if (str == QLatin1String("B0")) {
1052 return QPrinter::B0;
1053 } else if (str == QLatin1String("B1")) {
1054 return QPrinter::B1;
1055 } else if (str == QLatin1String("B10")) {
1056 return QPrinter::B10;
1057 } else if (str == QLatin1String("B2")) {
1058 return QPrinter::B2;
1059 } else if (str == QLatin1String("B3")) {
1060 return QPrinter::B3;
1061 } else if (str == QLatin1String("B4")) {
1062 return QPrinter::B4;
1063 } else if (str == QLatin1String("B6")) {
1064 return QPrinter::B6;
1065 } else if (str == QLatin1String("B7")) {
1066 return QPrinter::B7;
1067 } else if (str == QLatin1String("B8")) {
1068 return QPrinter::B8;
1069 } else if (str == QLatin1String("B9")) {
1070 return QPrinter::B9;
1071 } else if (str == QLatin1String("C5E")) {
1072 return QPrinter::C5E;
1073 } else if (str == QLatin1String("Comm10E")) {
1074 return QPrinter::Comm10E;
1075 } else if (str == QLatin1String("DLE")) {
1076 return QPrinter::DLE;
1077 } else if (str == QLatin1String("Folio")) {
1078 return QPrinter::Folio;
1079 } else if (str == QLatin1String("Ledger")) {
1080 return QPrinter::Ledger;
1081 } else if (str == QLatin1String("Tabloid")) {
1082 return QPrinter::Tabloid;
1083 } else {
1084 return QPrinter::Custom;
1085 }
1086}
1087
1088QString QPrinterInfoPrivate::pageSize2String(QPrinter::PaperSize size)
1089{
1090 switch (size) {
1091 case QPrinter::A4:
1092 return QLatin1String("A4");
1093 case QPrinter::B5:
1094 return QLatin1String("B5");
1095 case QPrinter::Letter:
1096 return QLatin1String("Letter");
1097 case QPrinter::Legal:
1098 return QLatin1String("Legal");
1099 case QPrinter::Executive:
1100 return QLatin1String("Executive");
1101 case QPrinter::A0:
1102 return QLatin1String("A0");
1103 case QPrinter::A1:
1104 return QLatin1String("A1");
1105 case QPrinter::A2:
1106 return QLatin1String("A2");
1107 case QPrinter::A3:
1108 return QLatin1String("A3");
1109 case QPrinter::A5:
1110 return QLatin1String("A5");
1111 case QPrinter::A6:
1112 return QLatin1String("A6");
1113 case QPrinter::A7:
1114 return QLatin1String("A7");
1115 case QPrinter::A8:
1116 return QLatin1String("A8");
1117 case QPrinter::A9:
1118 return QLatin1String("A9");
1119 case QPrinter::B0:
1120 return QLatin1String("B0");
1121 case QPrinter::B1:
1122 return QLatin1String("B1");
1123 case QPrinter::B10:
1124 return QLatin1String("B10");
1125 case QPrinter::B2:
1126 return QLatin1String("B2");
1127 case QPrinter::B3:
1128 return QLatin1String("B3");
1129 case QPrinter::B4:
1130 return QLatin1String("B4");
1131 case QPrinter::B6:
1132 return QLatin1String("B6");
1133 case QPrinter::B7:
1134 return QLatin1String("B7");
1135 case QPrinter::B8:
1136 return QLatin1String("B8");
1137 case QPrinter::B9:
1138 return QLatin1String("B9");
1139 case QPrinter::C5E:
1140 return QLatin1String("C5E");
1141 case QPrinter::Comm10E:
1142 return QLatin1String("Comm10E");
1143 case QPrinter::DLE:
1144 return QLatin1String("DLE");
1145 case QPrinter::Folio:
1146 return QLatin1String("Folio");
1147 case QPrinter::Ledger:
1148 return QLatin1String("Ledger");
1149 case QPrinter::Tabloid:
1150 return QLatin1String("Tabloid");
1151 default:
1152 return QLatin1String("Custom");
1153 }
1154}
1155
1156#endif // QT_NO_PRINTER
1157
1158QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.