Qt 4.8
qprinterinfo_unix.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qprinterinfo.h"
43 #include "qprinterinfo_p.h"
44 
45 #include <qfile.h>
46 #include <qfileinfo.h>
47 #include <qdir.h>
48 #include <qprintdialog.h>
49 #include <qlibrary.h>
50 #include <qtextstream.h>
51 
52 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
53 # include <private/qcups_p.h>
54 # include <cups/cups.h>
55 # include <private/qpdf_p.h>
56 #endif
57 
58 #include <private/qprinterinfo_unix_p.h>
59 
61 
62 #ifndef QT_NO_PRINTER
63 
64 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
65 // preserver names in ascending order for the binary search
66 static const struct NamedPaperSize {
67  const char *const name;
70  { "A0", QPrinter::A0 },
71  { "A1", QPrinter::A1 },
72  { "A2", QPrinter::A2 },
73  { "A3", QPrinter::A3 },
74  { "A4", QPrinter::A4 },
75  { "A5", QPrinter::A5 },
76  { "A6", QPrinter::A6 },
77  { "A7", QPrinter::A7 },
78  { "A8", QPrinter::A8 },
79  { "A9", QPrinter::A9 },
80  { "B0", QPrinter::B0 },
81  { "B1", QPrinter::B1 },
82  { "B10", QPrinter::B10 },
83  { "B2", QPrinter::B2 },
84  { "B4", QPrinter::B4 },
85  { "B5", QPrinter::B5 },
86  { "B6", QPrinter::B6 },
87  { "B7", QPrinter::B7 },
88  { "B8", QPrinter::B8 },
89  { "B9", QPrinter::B9 },
90  { "C5E", QPrinter::C5E },
91  { "Comm10E", QPrinter::Comm10E },
92  { "Custom", QPrinter::Custom },
93  { "DLE", QPrinter::DLE },
94  { "Executive", QPrinter::Executive },
95  { "Folio", QPrinter::Folio },
96  { "Ledger", QPrinter::Ledger },
97  { "Legal", QPrinter::Legal },
98  { "Letter", QPrinter::Letter },
99  { "Tabloid", QPrinter::Tabloid }
100 };
101 
102 inline bool operator<(const char *name, const NamedPaperSize &data)
103 { return qstrcmp(name, data.name) < 0; }
104 inline bool operator<(const NamedPaperSize &data, const char *name)
105 { return qstrcmp(data.name, name) < 0; }
106 
107 static inline QPrinter::PaperSize string2PaperSize(const char *name)
108 {
111  return r->size;
112  return QPrinter::Custom;
113 }
114 
115 static inline const char *paperSize2String(QPrinter::PaperSize size)
116 {
117  for (int i = 0; i < QPrinter::NPageSize; ++i) {
118  if (size == named_sizes_map[i].size)
119  return named_sizes_map[i].name;
120  }
121  return 0;
122 }
123 #endif
124 
126  QString host, QString comment,
128 {
129  for (int i = 0; i < printers->size(); ++i)
130  if (printers->at(i).samePrinter(name))
131  return;
132 
133 #ifndef QT_NO_PRINTDIALOG
134  if (host.isEmpty())
135  host = QPrintDialog::tr("locally connected");
136 #endif
137  printers->append(QPrinterDescription(name.simplified(), host.simplified(), comment.simplified(), aliases));
138 }
139 
141 {
142  if (printerDesc.length() < 1)
143  return;
144 
145  printerDesc = printerDesc.simplified();
146  int i = printerDesc.indexOf(QLatin1Char(':'));
147  QString printerName, printerComment, printerHost;
149 
150  if (i >= 0) {
151  // have ':' want '|'
152  int j = printerDesc.indexOf(QLatin1Char('|'));
153  if (j > 0 && j < i) {
154  printerName = printerDesc.left(j);
155  aliases = printerDesc.mid(j + 1, i - j - 1).split(QLatin1Char('|'));
156 #ifndef QT_NO_PRINTDIALOG
157  // try extracting a comment from the aliases
158  printerComment = QPrintDialog::tr("Aliases: %1")
159  .arg(aliases.join(QLatin1String(", ")));
160 #endif
161  } else {
162  printerName = printerDesc.left(i);
163  }
164  // look for lprng pseudo all printers entry
165  i = printerDesc.indexOf(QRegExp(QLatin1String(": *all *=")));
166  if (i >= 0)
167  printerName = QString();
168  // look for signs of this being a remote printer
169  i = printerDesc.indexOf(QRegExp(QLatin1String(": *rm *=")));
170  if (i >= 0) {
171  // point k at the end of remote host name
172  while (printerDesc[i] != QLatin1Char('='))
173  i++;
174  while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace())
175  i++;
176  j = i;
177  while (j < (int)printerDesc.length() && printerDesc[j] != QLatin1Char(':'))
178  j++;
179 
180  // and stuff that into the string
181  printerHost = printerDesc.mid(i, j - i);
182  }
183  }
184  if (printerName.length())
185  qt_perhapsAddPrinter(printers, printerName, printerHost, printerComment,
186  aliases);
187 }
188 
190 {
191  QFile printcap(fileName);
192  if (!printcap.open(QIODevice::ReadOnly))
193  return NotFound;
194 
195  char *line_ascii = new char[1025];
196  line_ascii[1024] = '\0';
197 
198  QString printerDesc;
199  bool atEnd = false;
200 
201  while (!atEnd) {
202  if (printcap.atEnd() || printcap.readLine(line_ascii, 1024) <= 0)
203  atEnd = true;
204  QString line = QString::fromLocal8Bit(line_ascii);
205  line = line.trimmed();
206  if (line.length() >= 1 && line[int(line.length()) - 1] == QLatin1Char('\\'))
207  line.chop(1);
208  if (line[0] == QLatin1Char('#')) {
209  if (!atEnd)
210  continue;
211  } else if (line[0] == QLatin1Char('|') || line[0] == QLatin1Char(':')
212  || line.isEmpty()) {
213  printerDesc += line;
214  if (!atEnd)
215  continue;
216  }
217 
218  qt_parsePrinterDesc(printerDesc, printers);
219 
220  // add the first line of the new printer definition
221  printerDesc = line;
222  }
223  delete[] line_ascii;
224  return Success;
225 }
226 
239 {
240  QFile file(QDir::homePath() + QLatin1String("/.printers"));
241  if (!file.open(QIODevice::ReadOnly))
242  return QString();
243  QString all(QLatin1String(file.readAll()));
245  const int i = words.indexOf(QLatin1String("_default"));
246  if (i != -1 && i < words.size() - 1)
247  return words.at(i + 1);
248  return QString();
249 }
250 
251 // solaris, not 2.6
253 {
254  QDir lp(QLatin1String("/etc/lp/printers"));
255  QFileInfoList dirs = lp.entryInfoList();
256  if (dirs.isEmpty())
257  return;
258 
259  QString tmp;
260  for (int i = 0; i < dirs.size(); ++i) {
261  QFileInfo printer = dirs.at(i);
262  if (printer.isDir()) {
263  tmp.sprintf("/etc/lp/printers/%s/configuration",
264  printer.fileName().toAscii().data());
265  QFile configuration(tmp);
266  char *line = new char[1025];
267  QString remote(QLatin1String("Remote:"));
268  QString contentType(QLatin1String("Content types:"));
269  QString printerHost;
270  bool canPrintPostscript = false;
271  if (configuration.open(QIODevice::ReadOnly)) {
272  while (!configuration.atEnd() &&
273  configuration.readLine(line, 1024) > 0) {
274  if (QString::fromLatin1(line).startsWith(remote)) {
275  const char *p = line;
276  while (*p != ':')
277  p++;
278  p++;
279  while (isspace((uchar) *p))
280  p++;
281  printerHost = QString::fromLocal8Bit(p);
282  printerHost = printerHost.simplified();
283  } else if (QString::fromLatin1(line).startsWith(contentType)) {
284  char *p = line;
285  while (*p != ':')
286  p++;
287  p++;
288  char *e;
289  while (*p) {
290  while (isspace((uchar) *p))
291  p++;
292  if (*p) {
293  char s;
294  e = p;
295  while (isalnum((uchar) *e))
296  e++;
297  s = *e;
298  *e = '\0';
299  if (!qstrcmp(p, "postscript") ||
300  !qstrcmp(p, "any"))
301  canPrintPostscript = true;
302  *e = s;
303  if (s == ',')
304  e++;
305  p = e;
306  }
307  }
308  }
309  }
310  if (canPrintPostscript)
311  qt_perhapsAddPrinter(printers, printer.fileName(),
312  printerHost, QLatin1String(""));
313  }
314  delete[] line;
315  }
316  }
317 }
318 
319 // solaris 2.6
321 {
322  QFile pc(QLatin1String("/etc/printers.conf"));
323  if (!pc.open(QIODevice::ReadOnly)) {
324  if (found)
325  *found = false;
326  return 0;
327  }
328  if (found)
329  *found = true;
330 
331  char *line = new char[1025];
332  line[1024] = '\0';
333 
334  QString printerDesc;
335  int lineLength = 0;
336 
337  char *defaultPrinter = 0;
338 
339  while (!pc.atEnd() &&
340  (lineLength=pc.readLine(line, 1024)) > 0) {
341  if (*line == '#') {
342  *line = '\0';
343  lineLength = 0;
344  }
345  if (lineLength >= 2 && line[lineLength-2] == '\\') {
346  line[lineLength-2] = '\0';
347  printerDesc += QString::fromLocal8Bit(line);
348  } else {
349  printerDesc += QString::fromLocal8Bit(line);
350  printerDesc = printerDesc.simplified();
351  int i = printerDesc.indexOf(QLatin1Char(':'));
352  QString printerName, printerHost, printerComment;
354  if (i >= 0) {
355  // have : want |
356  int j = printerDesc.indexOf(QLatin1Char('|'));
357  if (j >= i)
358  j = -1;
359  printerName = printerDesc.mid(0, j < 0 ? i : j);
360  if (printerName == QLatin1String("_default")) {
361  i = printerDesc.indexOf(
362  QRegExp(QLatin1String(": *use *=")));
363  while (printerDesc[i] != QLatin1Char('='))
364  i++;
365  while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace())
366  i++;
367  j = i;
368  while (j < (int)printerDesc.length() &&
369  printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(','))
370  j++;
371  // that's our default printer
372  defaultPrinter =
373  qstrdup(printerDesc.mid(i, j-i).toAscii().data());
374  printerName = QString();
375  printerDesc = QString();
376  } else if (printerName == QLatin1String("_all")) {
377  // skip it.. any other cases we want to skip?
378  printerName = QString();
379  printerDesc = QString();
380  }
381 
382  if (j > 0) {
383  // try extracting a comment from the aliases
384  aliases = printerDesc.mid(j + 1, i - j - 1).split(QLatin1Char('|'));
385 #ifndef QT_NO_PRINTDIALOG
386  printerComment = QPrintDialog::tr("Aliases: %1")
387  .arg(aliases.join(QLatin1String(", ")));
388 #endif
389  }
390  // look for signs of this being a remote printer
391  i = printerDesc.indexOf(
392  QRegExp(QLatin1String(": *bsdaddr *=")));
393  if (i >= 0) {
394  // point k at the end of remote host name
395  while (printerDesc[i] != QLatin1Char('='))
396  i++;
397  while (printerDesc[i] == QLatin1Char('=') || printerDesc[i].isSpace())
398  i++;
399  j = i;
400  while (j < (int)printerDesc.length() &&
401  printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(','))
402  j++;
403  // and stuff that into the string
404  printerHost = printerDesc.mid(i, j-i);
405  // maybe stick the remote printer name into the comment
406  if (printerDesc[j] == QLatin1Char(',')) {
407  i = ++j;
408  while (printerDesc[i].isSpace())
409  i++;
410  j = i;
411  while (j < (int)printerDesc.length() &&
412  printerDesc[j] != QLatin1Char(':') && printerDesc[j] != QLatin1Char(','))
413  j++;
414  if (printerName != printerDesc.mid(i, j-i)) {
415  printerComment =
416  QLatin1String("Remote name: ");
417  printerComment += printerDesc.mid(i, j-i);
418  }
419  }
420  }
421  }
422  if (printerComment == QLatin1String(":"))
423  printerComment = QString(); // for cups
424  if (printerName.length())
425  qt_perhapsAddPrinter(printers, printerName, printerHost,
426  printerComment, aliases);
427  // chop away the line, for processing the next one
428  printerDesc = QString();
429  }
430  }
431  delete[] line;
432  return defaultPrinter;
433 }
434 
435 #ifndef QT_NO_NIS
436 
437 #if defined(Q_C_CALLBACKS)
438 extern "C" {
439 #endif
440 
441 int qt_pd_foreach(int /*status */, char * /*key */, int /*keyLen */,
442  char *val, int valLen, char *data)
443 {
445  return 0;
446 }
447 
448 #if defined(Q_C_CALLBACKS)
449 }
450 #endif
451 
453 {
454 #ifndef QT_NO_LIBRARY
455  typedef int (*WildCast)(int, char *, int, char *, int, char *);
456  char printersConfByname[] = "printers.conf.byname";
457  char *domain;
458  int err;
459 
460  QLibrary lib(QLatin1String("nsl"));
461  typedef int (*ypGetDefaultDomain)(char **);
462  ypGetDefaultDomain _ypGetDefaultDomain = (ypGetDefaultDomain)lib.resolve("yp_get_default_domain");
463  typedef int (*ypAll)(const char *, const char *, const struct ypall_callback *);
464  ypAll _ypAll = (ypAll)lib.resolve("yp_all");
465 
466  if (_ypGetDefaultDomain && _ypAll) {
467  err = _ypGetDefaultDomain(&domain);
468  if (err == 0) {
469  ypall_callback cb;
470  // wild cast to support K&R-style system headers
471  (WildCast &) cb.foreach = (WildCast) qt_pd_foreach;
472  cb.data = (char *) printers;
473  err = _ypAll(domain, printersConfByname, &cb);
474  }
475  if (!err)
476  return Success;
477  }
478 #endif //QT_NO_LIBRARY
479  return Unavail;
480 }
481 
482 #endif // QT_NO_NIS
483 
485 {
486 #define skipSpaces() \
487  while (line[k] != '\0' && isspace((uchar) line[k])) \
488  k++
489 
490  char *defaultPrinter = 0;
491  bool stop = false;
492  int lastStatus = NotFound;
493 
494  int k = 8;
495  skipSpaces();
496  if (line[k] != ':')
497  return 0;
498  k++;
499 
500  char *cp = strchr(line, '#');
501  if (cp != 0)
502  *cp = '\0';
503 
504  while (line[k] != '\0') {
505  if (isspace((uchar) line[k])) {
506  k++;
507  } else if (line[k] == '[') {
508  k++;
509  skipSpaces();
510  while (line[k] != '\0') {
511  char status = tolower(line[k]);
512  char action = '?';
513 
514  while (line[k] != '=' && line[k] != ']' && line[k] != '\0')
515  k++;
516  if (line[k] == '=') {
517  k++;
518  skipSpaces();
519  action = tolower(line[k]);
520  while (line[k] != '\0' && !isspace((uchar) line[k]) && line[k] != ']')
521  k++;
522  } else if (line[k] == ']') {
523  k++;
524  break;
525  }
526  skipSpaces();
527 
528  if (lastStatus == status)
529  stop = (action == (char) Return);
530  }
531  } else {
532  if (stop)
533  break;
534 
535  QByteArray source;
536  while (line[k] != '\0' && !isspace((uchar) line[k]) && line[k] != '[') {
537  source += line[k];
538  k++;
539  }
540 
541  if (source == "user") {
542  lastStatus = qt_parsePrintcap(printers,
543  QDir::homePath() + QLatin1String("/.printers"));
544  } else if (source == "files") {
545  bool found;
546  defaultPrinter = qt_parsePrintersConf(printers, &found);
547  if (found)
548  lastStatus = Success;
549 #ifndef QT_NO_NIS
550  } else if (source == "nis") {
551  lastStatus = qt_retrieveNisPrinters(printers);
552 #endif
553  } else {
554  // nisplus, dns, etc., are not implemented yet
555  lastStatus = NotFound;
556  }
557  stop = (lastStatus == Success);
558  }
559  }
560  return defaultPrinter;
561 }
562 
564 {
565  QFile nc(QLatin1String("/etc/nsswitch.conf"));
566  if (!nc.open(QIODevice::ReadOnly))
567  return 0;
568 
569  char *defaultPrinter = 0;
570 
571  char *line = new char[1025];
572  line[1024] = '\0';
573 
574  while (!nc.atEnd() &&
575  nc.readLine(line, 1024) > 0) {
576  if (qstrncmp(line, "printers", 8) == 0) {
577  defaultPrinter = qt_parseNsswitchPrintersEntry(printers, line);
578  delete[] line;
579  return defaultPrinter;
580  }
581  }
582 
583  strcpy(line, "printers: user files nis nisplus xfn");
584  defaultPrinter = qt_parseNsswitchPrintersEntry(printers, line);
585  delete[] line;
586  return defaultPrinter;
587 }
588 
589 // HP-UX
591 {
592  QDir lp(QLatin1String("/etc/lp/member"));
593  if (!lp.exists())
594  return;
595  QFileInfoList dirs = lp.entryInfoList();
596  if (dirs.isEmpty())
597  return;
598 
599 #ifdef QT_NO_PRINTDIALOG
600  Q_UNUSED(printers);
601 #else
602  QString tmp;
603  for (int i = 0; i < dirs.size(); ++i) {
604  QFileInfo printer = dirs.at(i);
605  // I haven't found any real documentation, so I'm guessing that
606  // since lpstat uses /etc/lp/member rather than one of the
607  // other directories, it's the one to use. I did not find a
608  // decent way to locate aliases and remote printers.
609  if (printer.isFile())
610  qt_perhapsAddPrinter(printers, printer.fileName(),
611  QPrintDialog::tr("unknown"),
612  QLatin1String(""));
613  }
614 #endif
615 }
616 
617 // IRIX 6.x
619 {
620  QDir lp(QLatin1String("/usr/spool/lp/interface"));
621  if (!lp.exists())
622  return;
623  QFileInfoList files = lp.entryInfoList();
624  if(files.isEmpty())
625  return;
626 
627  for (int i = 0; i < files.size(); ++i) {
628  QFileInfo printer = files.at(i);
629 
630  if (!printer.isFile())
631  continue;
632 
633  // parse out some information
634  QFile configFile(printer.filePath());
635  if (!configFile.open(QIODevice::ReadOnly))
636  continue;
637 
638  QByteArray line;
639  line.resize(1025);
640  QString namePrinter;
641  QString hostName;
642  QString hostPrinter;
643  QString printerType;
644 
645  QString nameKey(QLatin1String("NAME="));
646  QString typeKey(QLatin1String("TYPE="));
647  QString hostKey(QLatin1String("HOSTNAME="));
648  QString hostPrinterKey(QLatin1String("HOSTPRINTER="));
649 
650  while (!configFile.atEnd() &&
651  (configFile.readLine(line.data(), 1024)) > 0) {
652  QString uline = QString::fromLocal8Bit(line);
653  if (uline.startsWith(typeKey) ) {
654  printerType = uline.mid(nameKey.length());
655  printerType = printerType.simplified();
656  } else if (uline.startsWith(hostKey)) {
657  hostName = uline.mid(hostKey.length());
658  hostName = hostName.simplified();
659  } else if (uline.startsWith(hostPrinterKey)) {
660  hostPrinter = uline.mid(hostPrinterKey.length());
661  hostPrinter = hostPrinter.simplified();
662  } else if (uline.startsWith(nameKey)) {
663  namePrinter = uline.mid(nameKey.length());
664  namePrinter = namePrinter.simplified();
665  }
666  }
667  configFile.close();
668 
669  printerType = printerType.trimmed();
670  if (printerType.indexOf(QLatin1String("postscript"), 0, Qt::CaseInsensitive) < 0)
671  continue;
672 
673  int ii = 0;
674  while ((ii = namePrinter.indexOf(QLatin1Char('"'), ii)) >= 0)
675  namePrinter.remove(ii, 1);
676 
677  if (hostName.isEmpty() || hostPrinter.isEmpty()) {
678  qt_perhapsAddPrinter(printers, printer.fileName(),
679  QLatin1String(""), namePrinter);
680  } else {
681  QString comment;
682  comment = namePrinter;
683  comment += QLatin1String(" (");
684  comment += hostPrinter;
685  comment += QLatin1Char(')');
686  qt_perhapsAddPrinter(printers, printer.fileName(),
687  hostName, comment);
688  }
689  }
690 }
691 
692 
693 // Every unix must have its own. It's a standard. Here is AIX.
695 {
696  QFile qconfig(QLatin1String("/etc/qconfig"));
697  if (!qconfig.open(QIODevice::ReadOnly))
698  return;
699 
700  QTextStream ts(&qconfig);
701  QString line;
702 
703  QString stanzaName; // either a queue or a device name
704  bool up = true; // queue up? default true, can be false
705  QString remoteHost; // null if local
706  QString deviceName; // null if remote
707 
708  QRegExp newStanza(QLatin1String("^[0-z\\-]*:$"));
709 
710  // our basic strategy here is to process each line, detecting new
711  // stanzas. each time we see a new stanza, we check if the
712  // previous stanza was a valid queue for a) a remote printer or b)
713  // a local printer. if it wasn't, we assume that what we see is
714  // the start of the first stanza, or that the previous stanza was
715  // a device stanza, or that there is some syntax error (we don't
716  // report those).
717 
718  do {
719  line = ts.readLine();
720  bool indented = line[0].isSpace();
721  line = line.simplified();
722 
723  int i = line.indexOf(QLatin1Char('='));
724  if (indented && i != -1) { // line in stanza
725  QString variable = line.left(i).simplified();
726  QString value=line.mid(i+1, line.length()).simplified();
727  if (variable == QLatin1String("device"))
728  deviceName = value;
729  else if (variable == QLatin1String("host"))
730  remoteHost = value;
731  else if (variable == QLatin1String("up"))
732  up = !(value.toLower() == QLatin1String("false"));
733  } else if (line[0] == QLatin1Char('*')) { // comment
734  // nothing to do
735  } else if (ts.atEnd() || // end of file, or beginning of new stanza
736  (!indented && line.contains(newStanza))) {
737  if (up && stanzaName.length() > 0 && stanzaName.length() < 21) {
738  if (remoteHost.length()) // remote printer
739  qt_perhapsAddPrinter(printers, stanzaName, remoteHost,
740  QString());
741  else if (deviceName.length()) // local printer
742  qt_perhapsAddPrinter(printers, stanzaName, QString(),
743  QString());
744  }
745  line.chop(1);
746  if (line.length() >= 1 && line.length() <= 20)
747  stanzaName = line;
748  up = true;
749  remoteHost.clear();
750  deviceName.clear();
751  } else {
752  // syntax error? ignore.
753  }
754  } while (!ts.atEnd());
755 }
756 
758 {
759  QByteArray etcLpDefault;
760  qt_parsePrintcap(&printers, QLatin1String("/etc/printcap"));
761  qt_parseEtcLpMember(&printers);
762  qt_parseSpoolInterface(&printers);
763  qt_parseQconfig(&printers);
764 
765  QFileInfo f;
766  f.setFile(QLatin1String("/etc/lp/printers"));
767  if (f.isDir()) {
768  qt_parseEtcLpPrinters(&printers);
769  QFile def(QLatin1String("/etc/lp/default"));
770  if (def.open(QIODevice::ReadOnly)) {
771  etcLpDefault.resize(1025);
772  if (def.readLine(etcLpDefault.data(), 1024) > 0) {
773  QRegExp rx(QLatin1String("^(\\S+)"));
774  if (rx.indexIn(QString::fromLatin1(etcLpDefault)) != -1)
775  etcLpDefault = rx.cap(1).toAscii();
776  }
777  }
778  }
779 
780  char *def = 0;
781  f.setFile(QLatin1String("/etc/nsswitch.conf"));
782  if (f.isFile()) {
783  def = qt_parseNsswitchConf(&printers);
784  } else {
785  f.setFile(QLatin1String("/etc/printers.conf"));
786  if (f.isFile())
787  def = qt_parsePrintersConf(&printers);
788  }
789 
790  if (def) {
791  etcLpDefault = def;
792  delete [] def;
793  }
794 
795  QString homePrintersDefault = qt_getDefaultFromHomePrinters();
796 
797  // all printers hopefully known. try to find a good default
798  QString dollarPrinter;
799  {
800  dollarPrinter = QString::fromLocal8Bit(qgetenv("PRINTER"));
801  if (dollarPrinter.isEmpty())
802  dollarPrinter = QString::fromLocal8Bit(qgetenv("LPDEST"));
803  if (dollarPrinter.isEmpty())
804  dollarPrinter = QString::fromLocal8Bit(qgetenv("NPRINTER"));
805  if (dollarPrinter.isEmpty())
806  dollarPrinter = QString::fromLocal8Bit(qgetenv("NGPRINTER"));
807 #ifndef QT_NO_PRINTDIALOG
808  if (!dollarPrinter.isEmpty())
809  qt_perhapsAddPrinter(&printers, dollarPrinter,
810  QPrintDialog::tr("unknown"),
811  QLatin1String(""));
812 #endif
813  }
814 
815  QRegExp ps(QLatin1String("[^a-z]ps(?:[^a-z]|$)"));
816  QRegExp lp(QLatin1String("[^a-z]lp(?:[^a-z]|$)"));
817 
818  int quality = 0;
819  int best = 0;
820  for (int i = 0; i < printers.size(); ++i) {
821  QString name = printers.at(i).name;
822  QString comment = printers.at(i).comment;
823  if (quality < 5 && name == dollarPrinter) {
824  best = i;
825  quality = 5;
826  } else if (quality < 4 && !homePrintersDefault.isEmpty() &&
827  name == homePrintersDefault) {
828  best = i;
829  quality = 4;
830  } else if (quality < 3 && !etcLpDefault.isEmpty() &&
831  name == QLatin1String(etcLpDefault)) {
832  best = i;
833  quality = 3;
834  } else if (quality < 2 &&
835  (name == QLatin1String("ps") ||
836  ps.indexIn(comment) != -1)) {
837  best = i;
838  quality = 2;
839  } else if (quality < 1 &&
840  (name == QLatin1String("lp") ||
841  lp.indexIn(comment) > -1)) {
842  best = i;
843  quality = 1;
844  }
845  }
846 
847  return best;
848 }
849 
852 
854 {
855  QList<QPrinterInfo> printers;
856 
857 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
859  QCUPSSupport cups;
860  int cupsPrinterCount = cups.availablePrintersCount();
861  const cups_dest_t* cupsPrinters = cups.availablePrinters();
862  for (int i = 0; i < cupsPrinterCount; ++i) {
863  QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
864  if (cupsPrinters[i].instance)
865  printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
866 
867  QPrinterInfo printerInfo(printerName);
868  if (cupsPrinters[i].is_default)
869  printerInfo.d_ptr->isDefault = true;
870  printerInfo.d_ptr->cupsPrinterIndex = i;
871  printers.append(printerInfo);
872  }
873  } else
874 #endif
875  {
876  QList<QPrinterDescription> lprPrinters;
877  int defprn = qt_getLprPrinters(lprPrinters);
878  // populating printer combo
879  foreach (const QPrinterDescription &description, lprPrinters)
880  printers.append(QPrinterInfo(description.name));
881  if (defprn >= 0 && defprn < printers.size())
882  printers[defprn].d_ptr->isDefault = true;
883  }
884 
885  return printers;
886 }
887 
889 {
890  QList<QPrinterInfo> printers = availablePrinters();
891  foreach (const QPrinterInfo &printerInfo, printers) {
892  if (printerInfo.isDefault())
893  return printerInfo;
894  }
895 
896  return printers.value(0);
897 }
898 
900 {
901 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
902  const Q_D(QPrinterInfo);
903 
904  if (isNull())
905  return d->paperSizes;
906 
907  if (!d->hasPaperSizes) {
908  d->hasPaperSizes = true;
909 
911  // Find paper sizes from CUPS.
912  QCUPSSupport cups;
913  cups.setCurrentPrinter(d->cupsPrinterIndex);
914  const ppd_option_t* sizes = cups.pageSizes();
915  if (sizes) {
916  for (int j = 0; j < sizes->num_choices; ++j)
917  d->paperSizes.append(string2PaperSize(sizes->choices[j].choice));
918  }
919  }
920  }
921 
922  return d->paperSizes;
923 #else
925 #endif
926 }
927 
928 #endif // QT_NO_PRINTER
929 
void qt_parseEtcLpMember(QList< QPrinterDescription > *printers)
The QDir class provides access to directory structures and their contents.
Definition: qdir.h:58
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
double d
Definition: qnumeric_p.h:62
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
static QPrinterInfo defaultPrinter()
Returns the default printer on the system.
QString & sprintf(const char *format,...)
Safely builds a formatted string from the format string cformat and an arbitrary list of arguments...
Definition: qstring.cpp:5567
static QString fromLocal8Bit(const char *, int size=-1)
Returns a QString initialized with the first size characters of the 8-bit string str.
Definition: qstring.cpp:4245
QList< QPrinter::PaperSize > supportedPaperSizes() const
Returns a list of supported paper sizes by the printer.
QString cap(int nth=0) const
Returns the text captured by the nth subexpression.
Definition: qregexp.cpp:4310
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int availablePrintersCount() const
Definition: qcups.cpp:163
QString readLine(qint64 maxlen=0)
Reads one line of text from the stream, and returns it as a QString.
#define skipSpaces()
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
const char * aliases[7]
int qt_pd_foreach(int, char *, int, char *val, int valLen, char *data)
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
QString qt_getDefaultFromHomePrinters()
Checks $HOME/.
int qt_retrieveNisPrinters(QList< QPrinterDescription > *printers)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void chop(int n)
Removes n characters from the end of the string.
Definition: qstring.cpp:4623
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString fileName() const
Returns the name of the file, excluding the path.
Definition: qfileinfo.cpp:726
void qt_parseSpoolInterface(QList< QPrinterDescription > *printers)
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
Definition: qalgorithms.h:295
void * resolve(const char *symbol)
Returns the address of the exported symbol symbol.
Definition: qlibrary.cpp:1155
The QString class provides a Unicode character string.
Definition: qstring.h:83
char * qt_parseNsswitchConf(QList< QPrinterDescription > *printers)
const cups_dest_t * availablePrinters() const
Definition: qcups.cpp:168
static bool isAvailable()
Definition: qcups.cpp:216
#define Q_D(Class)
Definition: qglobal.h:2482
bool exists() const
Returns true if the directory exists; otherwise returns false.
Definition: qdir.cpp:1560
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
unsigned char uchar
Definition: qglobal.h:994
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
int indexOf(const QRegExp &rx, int from=0) const
Returns the index position of the first exact match of rx in the list, searching forward from index p...
Definition: qstringlist.h:195
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
const ppd_option_t * pageSizes() const
Definition: qcups.cpp:259
int indexIn(const QString &str, int offset=0, CaretMode caretMode=CaretAtZero) const
Attempts to find a match in str from position offset (0 by default).
Definition: qregexp.cpp:4136
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory; otherwise ret...
Definition: qfileinfo.cpp:990
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
QString trimmed() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end.
Definition: qstring.cpp:4506
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
int qt_getLprPrinters(QList< QPrinterDescription > &printers)
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void setFile(const QString &file)
Sets the file that the QFileInfo provides information about to file.
Definition: qfileinfo.cpp:468
static const char * data(const QByteArray &arr)
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QFileInfoList entryInfoList(Filters filters=NoFilter, SortFlags sort=NoSort) const
Returns a list of QFileInfo objects for all the files and directories in the directory, ordered according to the name and attribute filters previously set with setNameFilters() and setFilter(), and sorted according to the flags set with setSorting().
Definition: qdir.cpp:1316
T value(int i) const
Returns the value at index position i in the list.
Definition: qlist.h:661
static const struct NamedPaperSize named_sizes_map[QPrinter::NPageSize]
void qt_parseEtcLpPrinters(QList< QPrinterDescription > *printers)
void qt_parsePrinterDesc(QString printerDesc, QList< QPrinterDescription > *printers)
bool isDefault() const
Returns whether this printer is the default printer.
The QPrinterInfo class gives access to information about existing printers.
Definition: qprinterinfo.h:58
QString join(const QString &sep) const
Joins all the string list&#39;s strings into a single string with each element separated by the given sep...
Definition: qstringlist.h:162
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
const ppd_file_t * setCurrentPrinter(int index)
Definition: qcups.cpp:178
The QTextStream class provides a convenient interface for reading and writing text.
Definition: qtextstream.h:73
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes...
Definition: qiodevice.cpp:1110
QString simplified() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end, and that has each sequence o...
Definition: qstring.cpp:4415
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
Q_CORE_EXPORT char * qstrdup(const char *)
QScopedPointer< QPrinterInfoPrivate, QPrinterInfoPrivateDeleter > d_ptr
Definition: qprinterinfo.h:81
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
PaperSize
This enum type specifies what paper size QPrinter should use.
Definition: qprinter.h:91
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
void resize(int size)
Sets the size of the byte array to size bytes.
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QByteArray toAscii() const Q_REQUIRED_RESULT
Returns an 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4014
int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qbytearray.h:101
static QList< QPrinterInfo > availablePrinters()
Returns a list of available printers on the system.
bool isFile() const
Returns true if this object points to a file or to a symbolic link to a file.
Definition: qfileinfo.cpp:971
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
QPrinter::PaperSize size
bool samePrinter(const QString &printer) const
void qt_perhapsAddPrinter(QList< QPrinterDescription > *printers, const QString &name, QString host, QString comment, QStringList aliases)
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
int qstrcmp(const QByteArray &str1, const char *str2)
Definition: qbytearray.cpp:336
int qt_parsePrintcap(QList< QPrinterDescription > *printers, const QString &fileName)
bool atEnd() const
Returns true if there is no more data to be read from the QTextStream; otherwise returns false...
QString & remove(int i, int len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition: qstring.cpp:1867
bool operator<(const char *name, const NamedPaperSize &data)
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
bool atEnd() const
Returns true if the end of the file has been reached; otherwise returns false.
Definition: qfile.cpp:1735
char * qt_parseNsswitchPrintersEntry(QList< QPrinterDescription > *printers, char *line)
static QPrinter::PaperSize string2PaperSize(const char *name)
QString filePath() const
Returns the file name, including the path (which may be absolute or relative).
Definition: qfileinfo.cpp:707
void qt_parseQconfig(QList< QPrinterDescription > *printers)
static const char * paperSize2String(QPrinter::PaperSize size)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QString fileName(const QString &fileUrl)
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
static bool isNull(const QVariant::Private *d)
Definition: qvariant.cpp:300
The QLibrary class loads shared libraries at runtime.
Definition: qlibrary.h:62
char * qt_parsePrintersConf(QList< QPrinterDescription > *printers, bool *found)
const char *const name
static QString homePath()
Returns the absolute path of the user&#39;s home directory.
Definition: qdir.cpp:1942