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

Last change on this file since 441 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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