source: trunk/src/gui/dialogs/qprintdialog_unix.cpp@ 182

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

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

File size: 40.2 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 "qplatformdefs.h"
43
44#ifndef QT_NO_PRINTDIALOG
45
46#include "private/qabstractprintdialog_p.h"
47#include "qfiledialog_p.h"
48#include <QtGui/qmessagebox.h>
49#include "qprintdialog.h"
50#include "qfiledialog.h"
51#include <QtCore/qdir.h>
52#include <QtGui/qfilesystemmodel.h>
53#include <QtGui/qstyleditemdelegate.h>
54#include <QtGui/qprinter.h>
55
56#include <QtGui/qdialogbuttonbox.h>
57
58#include "ui_qprintpropertieswidget.h"
59#include "ui_qprintsettingsoutput.h"
60#include "ui_qprintwidget.h"
61
62#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
63# include <private/qcups_p.h>
64# include <cups/cups.h>
65# include <private/qpdf_p.h>
66#else
67# include <QtCore/qlibrary.h>
68#endif
69
70#include <private/qprinterinfo_unix_p.h>
71
72QT_BEGIN_NAMESPACE
73
74extern int qt_printerRealNumCopies(QPaintEngine *);
75
76class QOptionTreeItem;
77class QPPDOptionsModel;
78
79class QPrintPropertiesDialog : public QDialog
80{
81 Q_OBJECT
82public:
83 QPrintPropertiesDialog(QAbstractPrintDialog *parent = 0);
84 ~QPrintPropertiesDialog();
85
86#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
87 void setCups(QCUPSSupport *cups) { m_cups = cups; }
88 void addItemToOptions(QOptionTreeItem *parent, QList<const ppd_option_t*>& options, QList<const char*>& markedOptions) const;
89#endif
90
91 void selectPrinter();
92 void selectPdfPsPrinter(const QPrinter *p);
93
94 /// copy printer properties to the widget
95 void applyPrinterProperties(QPrinter *p);
96 void setupPrinter() const;
97
98protected:
99 void showEvent(QShowEvent* event);
100
101private:
102 Ui::QPrintPropertiesWidget widget;
103 QDialogButtonBox *m_buttons;
104#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
105 QCUPSSupport *m_cups;
106 QPPDOptionsModel *m_cupsOptionsModel;
107#endif
108};
109
110class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
111{
112 Q_DECLARE_PUBLIC(QPrintDialog)
113 Q_DECLARE_TR_FUNCTIONS(QPrintDialog)
114public:
115 QPrintDialogPrivate();
116 ~QPrintDialogPrivate();
117
118 void init();
119 /// copy printer properties to the widget
120 void applyPrinterProperties(QPrinter *p);
121
122#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
123 void selectPrinter(QCUPSSupport *cups);
124#endif
125
126 void _q_chbPrintLastFirstToggled(bool);
127#ifndef QT_NO_MESSAGEBOX
128 void _q_checkFields();
129#endif
130 void _q_collapseOrExpandDialog();
131
132 void setupPrinter();
133 void updateWidgets();
134
135 virtual void setTabs(const QList<QWidget*> &tabs);
136
137 Ui::QPrintSettingsOutput options;
138 QUnixPrintWidget *top;
139 QWidget *bottom;
140 QDialogButtonBox *buttons;
141 QPushButton *collapseButton;
142};
143
144#if defined (Q_OS_UNIX)
145class QUnixPrintWidgetPrivate
146{
147public:
148 QUnixPrintWidgetPrivate(QUnixPrintWidget *q);
149 ~QUnixPrintWidgetPrivate();
150
151 /// copy printer properties to the widget
152 void applyPrinterProperties(QPrinter *p);
153 bool checkFields();
154 void setupPrinter();
155 void setOptionsPane(QPrintDialogPrivate *pane);
156
157// slots
158 void _q_printerChanged(int index);
159 void _q_btnPropertiesClicked();
160 void _q_btnBrowseClicked();
161
162 QUnixPrintWidget * const parent;
163 QPrintPropertiesDialog *propertiesDialog;
164 Ui::QPrintWidget widget;
165 QAbstractPrintDialog * q;
166 QPrinter *printer;
167 QList<QPrinterDescription> lprPrinters;
168 void updateWidget();
169
170private:
171 QPrintDialogPrivate *optionsPane;
172 bool filePrintersAdded;
173#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
174 QCUPSSupport* cups;
175 int cupsPrinterCount;
176 const cups_dest_t* cupsPrinters;
177 const ppd_file_t* cupsPPD;
178#endif
179};
180#endif
181
182#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
183class QOptionTreeItem
184{
185public:
186 enum ItemType { Root, Group, Option, Choice };
187
188 QOptionTreeItem(ItemType t, int i, const void* p, const char* desc, QOptionTreeItem* pi)
189 : type(t),
190 index(i),
191 ptr(p),
192 description(desc),
193 selected(-1),
194 selDescription(0),
195 parentItem(pi) {};
196
197 ~QOptionTreeItem() {
198 while (!childItems.isEmpty())
199 delete childItems.takeFirst();
200 };
201
202 ItemType type;
203 int index;
204 const void* ptr;
205 const char* description;
206 int selected;
207 const char* selDescription;
208 QOptionTreeItem* parentItem;
209 QList<QOptionTreeItem*> childItems;
210};
211
212class QPPDOptionsModel : public QAbstractItemModel
213{
214 friend class QPPDOptionsEditor;
215public:
216 QPPDOptionsModel(QCUPSSupport *cups, QObject *parent = 0);
217 ~QPPDOptionsModel();
218
219 int columnCount(const QModelIndex& parent = QModelIndex()) const;
220 int rowCount(const QModelIndex& parent = QModelIndex()) const;
221 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
222 QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
223 QModelIndex parent(const QModelIndex& index) const;
224 Qt::ItemFlags flags(const QModelIndex& index) const;
225 QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
226
227 QOptionTreeItem* rootItem;
228 QCUPSSupport *cups;
229 const ppd_file_t* ppd;
230 void parseItems();
231 void parseGroups(QOptionTreeItem* parent);
232 void parseOptions(QOptionTreeItem* parent);
233 void parseChoices(QOptionTreeItem* parent);
234};
235
236class QPPDOptionsEditor : public QStyledItemDelegate
237{
238 Q_OBJECT
239public:
240 QPPDOptionsEditor(QObject* parent = 0) : QStyledItemDelegate(parent) {};
241 ~QPPDOptionsEditor() {};
242
243 QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
244 void setEditorData(QWidget* editor, const QModelIndex& index) const;
245 void setModelData( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;
246
247private slots:
248 void cbChanged(int index);
249
250};
251
252#endif
253
254////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
255
256QPrintPropertiesDialog::QPrintPropertiesDialog(QAbstractPrintDialog *parent)
257 : QDialog(parent)
258#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
259 , m_cups(0), m_cupsOptionsModel(0)
260#endif
261{
262 QVBoxLayout *lay = new QVBoxLayout(this);
263 this->setLayout(lay);
264 QWidget *content = new QWidget(this);
265 widget.setupUi(content);
266 m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
267 lay->addWidget(content);
268 lay->addWidget(m_buttons);
269
270 connect(m_buttons->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept()));
271 connect(m_buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
272}
273
274QPrintPropertiesDialog::~QPrintPropertiesDialog()
275{
276#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
277 delete m_cupsOptionsModel;
278#else
279 delete widget.cupsPropertiesPage;
280#endif
281}
282
283void QPrintPropertiesDialog::applyPrinterProperties(QPrinter *p)
284{
285 widget.pageSetup->setPrinter(p);
286}
287
288void QPrintPropertiesDialog::setupPrinter() const
289{
290 widget.pageSetup->setupPrinter();
291
292#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
293 QPPDOptionsModel* model = static_cast<QPPDOptionsModel*>(widget.treeView->model());
294 if (model) {
295 QOptionTreeItem* rootItem = model->rootItem;
296 QList<const ppd_option_t*> options;
297 QList<const char*> markedOptions;
298
299 addItemToOptions(rootItem, options, markedOptions);
300 model->cups->saveOptions(options, markedOptions);
301 }
302#endif
303}
304
305void QPrintPropertiesDialog::selectPrinter()
306{
307#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
308 widget.pageSetup->selectPrinter(m_cups);
309 widget.treeView->setModel(0);
310 if (m_cups && QCUPSSupport::isAvailable()) {
311
312 if (m_cupsOptionsModel == 0) {
313 m_cupsOptionsModel = new QPPDOptionsModel(m_cups);
314
315 widget.treeView->setItemDelegate(new QPPDOptionsEditor(this));
316 } else {
317 // update the model
318 m_cupsOptionsModel->parseItems();
319 }
320
321 if (m_cupsOptionsModel->rowCount() > 0) {
322 widget.treeView->setModel(m_cupsOptionsModel);
323
324 for (int i = 0; i < m_cupsOptionsModel->rowCount(); ++i)
325 widget.treeView->expand(m_cupsOptionsModel->index(i,0));
326
327 widget.tabs->setTabEnabled(1, true); // enable the advanced tab
328 } else {
329 widget.tabs->setTabEnabled(1, false);
330 }
331
332 } else
333#endif
334 {
335 widget.cupsPropertiesPage->setEnabled(false);
336 widget.pageSetup->selectPrinter(0);
337 }
338}
339
340void QPrintPropertiesDialog::selectPdfPsPrinter(const QPrinter *p)
341{
342 widget.treeView->setModel(0);
343 widget.pageSetup->selectPdfPsPrinter(p);
344 widget.tabs->setTabEnabled(1, false); // disable the advanced tab
345}
346
347void QPrintPropertiesDialog::showEvent(QShowEvent* event)
348{
349 widget.treeView->resizeColumnToContents(0);
350 event->accept();
351}
352
353#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
354void QPrintPropertiesDialog::addItemToOptions(QOptionTreeItem *parent, QList<const ppd_option_t*>& options, QList<const char*>& markedOptions) const
355{
356 for (int i = 0; i < parent->childItems.count(); ++i) {
357 QOptionTreeItem *itm = parent->childItems.at(i);
358 if (itm->type == QOptionTreeItem::Option) {
359 const ppd_option_t* opt = reinterpret_cast<const ppd_option_t*>(itm->ptr);
360 options << opt;
361 if (qstrcmp(opt->defchoice, opt->choices[itm->selected].choice) != 0) {
362 markedOptions << opt->keyword << opt->choices[itm->selected].choice;
363 }
364 } else {
365 addItemToOptions(itm, options, markedOptions);
366 }
367 }
368}
369#endif
370
371QPrintDialogPrivate::QPrintDialogPrivate()
372 : top(0), bottom(0), buttons(0), collapseButton(0)
373{
374}
375
376QPrintDialogPrivate::~QPrintDialogPrivate()
377{
378}
379
380void QPrintDialogPrivate::init()
381{
382 Q_Q(QPrintDialog);
383
384 top = new QUnixPrintWidget(0, q);
385 bottom = new QWidget(q);
386 options.setupUi(bottom);
387 options.color->setIconSize(QSize(32, 32));
388 options.color->setIcon(QIcon(QLatin1String(":/trolltech/dialogs/qprintdialog/images/status-color.png")));
389 options.grayscale->setIconSize(QSize(32, 32));
390 options.grayscale->setIcon(QIcon(QLatin1String(":/trolltech/dialogs/qprintdialog/images/status-gray-scale.png")));
391 top->d->setOptionsPane(this);
392
393 buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);
394 collapseButton = new QPushButton(QPrintDialog::tr("&Options >>"), buttons);
395 buttons->addButton(collapseButton, QDialogButtonBox::ResetRole);
396 bottom->setVisible(false);
397
398 QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);
399 printButton->setText(QPrintDialog::tr("&Print"));
400 printButton->setDefault(true);
401
402 QVBoxLayout *lay = new QVBoxLayout(q);
403 q->setLayout(lay);
404 lay->addWidget(top);
405 lay->addWidget(bottom);
406 lay->addWidget(buttons);
407
408 QPrinter* p = q->printer();
409
410 applyPrinterProperties(p);
411
412#ifdef QT_NO_MESSAGEBOX
413 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
414#else
415 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));
416#endif
417 QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));
418
419 QObject::connect(options.reverse, SIGNAL(toggled(bool)),
420 q, SLOT(_q_chbPrintLastFirstToggled(bool)));
421
422 QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
423}
424
425void QPrintDialogPrivate::applyPrinterProperties(QPrinter *p)
426{
427 if (p->colorMode() == QPrinter::Color)
428 options.color->setChecked(true);
429 else
430 options.grayscale->setChecked(true);
431
432 switch(p->duplex()) {
433 case QPrinter::DuplexNone:
434 options.noDuplex->setChecked(true); break;
435 case QPrinter::DuplexLongSide:
436 case QPrinter::DuplexAuto:
437 options.duplexLong->setChecked(true); break;
438 case QPrinter::DuplexShortSide:
439 options.duplexShort->setChecked(true); break;
440 }
441 options.copies->setValue(qt_printerRealNumCopies(p->paintEngine()));
442 options.collate->setChecked(p->collateCopies());
443 options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
444 top->d->applyPrinterProperties(p);
445}
446
447void QPrintDialogPrivate::_q_chbPrintLastFirstToggled(bool checked)
448{
449 Q_Q(QPrintDialog);
450 if (checked)
451 q->printer()->setPageOrder(QPrinter::LastPageFirst);
452 else
453 q->printer()->setPageOrder(QPrinter::FirstPageFirst);
454}
455
456void QPrintDialogPrivate::_q_collapseOrExpandDialog()
457{
458 int collapseHeight = 0;
459 Q_Q(QPrintDialog);
460 QWidget *widgetToHide = bottom;
461 if (widgetToHide->isVisible()) {
462 collapseButton->setText(QPrintDialog::tr("&Options >>"));
463 collapseHeight = widgetToHide->y() + widgetToHide->height() - (top->y() + top->height());
464 }
465 else
466 collapseButton->setText(QPrintDialog::tr("&Options <<"));
467 widgetToHide->setVisible(! widgetToHide->isVisible());
468 if (! widgetToHide->isVisible()) { // make it shrink
469 q->layout()->activate();
470 q->resize( QSize(q->width(), q->height() - collapseHeight) );
471 }
472}
473
474#ifndef QT_NO_MESSAGEBOX
475void QPrintDialogPrivate::_q_checkFields()
476{
477 Q_Q(QPrintDialog);
478 if (top->d->checkFields())
479 q->accept();
480}
481#endif // QT_NO_MESSAGEBOX
482
483void QPrintDialogPrivate::setupPrinter()
484{
485 Q_Q(QPrintDialog);
486 QPrinter* p = q->printer();
487
488 if (options.duplex->isEnabled()) {
489 if (options.noDuplex->isChecked())
490 p->setDuplex(QPrinter::DuplexNone);
491 else if (options.duplexLong->isChecked())
492 p->setDuplex(QPrinter::DuplexLongSide);
493 else
494 p->setDuplex(QPrinter::DuplexShortSide);
495 }
496
497 p->setColorMode( options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale );
498
499 // print range
500 if (options.printAll->isChecked()) {
501 p->setPrintRange(QPrinter::AllPages);
502 p->setFromTo(0,0);
503 } else if (options.printSelection->isChecked()) {
504 p->setPrintRange(QPrinter::Selection);
505 p->setFromTo(0,0);
506 } else if (options.printRange->isChecked()) {
507 p->setPrintRange(QPrinter::PageRange);
508 p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
509 }
510
511 // copies
512 p->setNumCopies(options.copies->value());
513 p->setCollateCopies(options.collate->isChecked());
514
515 top->d->setupPrinter();
516}
517
518void QPrintDialogPrivate::updateWidgets()
519{
520 Q_Q(QPrintDialog);
521 options.gbPrintRange->setVisible(q->isOptionEnabled(QPrintDialog::PrintPageRange) ||
522 q->isOptionEnabled(QPrintDialog::PrintSelection));
523
524 options.printRange->setEnabled(q->isOptionEnabled(QPrintDialog::PrintPageRange));
525 options.printSelection->setVisible(q->isOptionEnabled(QPrintDialog::PrintSelection));
526 options.collate->setVisible(q->isOptionEnabled(QPrintDialog::PrintCollateCopies));
527
528 switch (q->printRange()) {
529 case QPrintDialog::AllPages:
530 options.printAll->setChecked(true);
531 break;
532 case QPrintDialog::Selection:
533 options.printSelection->setChecked(true);
534 break;
535 case QPrintDialog::PageRange:
536 options.printRange->setChecked(true);
537 break;
538 default:
539 break;
540 }
541 const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));
542 const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());
543
544 options.from->setMinimum(minPage);
545 options.to->setMinimum(minPage);
546 options.from->setMaximum(maxPage);
547 options.to->setMaximum(maxPage);
548
549 options.from->setValue(q->fromPage());
550 options.to->setValue(q->toPage());
551 top->d->updateWidget();
552}
553
554void QPrintDialogPrivate::setTabs(const QList<QWidget*> &tabWidgets)
555{
556 while(options.tabs->count() > 2)
557 delete options.tabs->widget(2);
558
559 QList<QWidget*>::ConstIterator iter = tabWidgets.begin();
560 while(iter != tabWidgets.constEnd()) {
561 QWidget *tab = *iter;
562 options.tabs->addTab(tab, tab->windowTitle());
563 ++iter;
564 }
565}
566
567#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
568void QPrintDialogPrivate::selectPrinter(QCUPSSupport *cups)
569{
570 options.duplex->setEnabled(cups && cups->ppdOption("Duplex"));
571}
572#endif
573
574////////////////////////////////////////////////////////////////////////////////
575
576QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
577 : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
578{
579 Q_D(QPrintDialog);
580 d->init();
581}
582
583/*!
584 Constructs a print dialog with the given \a parent.
585*/
586QPrintDialog::QPrintDialog(QWidget *parent)
587 : QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent)
588{
589 Q_D(QPrintDialog);
590 d->init();
591}
592
593QPrintDialog::~QPrintDialog()
594{
595}
596
597void QPrintDialog::setVisible(bool visible)
598{
599 Q_D(QPrintDialog);
600
601 if (visible)
602 d->updateWidgets();
603
604 QAbstractPrintDialog::setVisible(visible);
605}
606
607int QPrintDialog::exec()
608{
609 return QDialog::exec();
610}
611
612void QPrintDialog::accept()
613{
614 Q_D(QPrintDialog);
615 d->setupPrinter();
616 QDialog::accept();
617}
618
619#ifdef QT3_SUPPORT
620QPrinter *QPrintDialog::printer() const
621{
622 Q_D(const QPrintDialog);
623 return d->printer;
624}
625
626void QPrintDialog::setPrinter(QPrinter *printer, bool pickupSettings)
627{
628 if (!printer)
629 return;
630
631 Q_D(QPrintDialog);
632 d->printer = printer;
633
634 if (pickupSettings)
635 d->applyPrinterProperties(printer);
636}
637
638void QPrintDialog::addButton(QPushButton *button)
639{
640 Q_D(QPrintDialog);
641 d->buttons->addButton(button, QDialogButtonBox::HelpRole);
642}
643#endif // QT3_SUPPORT
644
645#if defined (Q_OS_UNIX)
646
647/*! \internal
648*/
649QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p)
650 : parent(p), propertiesDialog(0), printer(0), optionsPane(0), filePrintersAdded(false)
651#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
652 , cups(0), cupsPrinterCount(0), cupsPrinters(0), cupsPPD(0)
653#endif
654{
655 q = 0;
656 if (parent)
657 q = qobject_cast<QAbstractPrintDialog*> (parent->parent());
658
659 widget.setupUi(parent);
660
661 int currentPrinterIndex = 0;
662#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
663 cups = new QCUPSSupport;
664 if (QCUPSSupport::isAvailable()) {
665 cupsPPD = cups->currentPPD();
666 cupsPrinterCount = cups->availablePrintersCount();
667 cupsPrinters = cups->availablePrinters();
668
669 for (int i = 0; i < cupsPrinterCount; ++i) {
670 QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
671 if (cupsPrinters[i].instance)
672 printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance);
673
674 widget.printers->addItem(printerName);
675 if (cupsPrinters[i].is_default)
676 widget.printers->setCurrentIndex(i);
677 }
678 // the model depends on valid ppd. so before enabling the
679 // properties button we make sure the ppd is in fact valid.
680 if (cupsPrinterCount && cups->currentPPD()) {
681 widget.properties->setEnabled(true);
682 }
683 currentPrinterIndex = cups->currentPrinterIndex();
684 } else {
685#endif
686 currentPrinterIndex = qt_getLprPrinters(lprPrinters);
687 // populating printer combo
688 QList<QPrinterDescription>::const_iterator i = lprPrinters.constBegin();
689 for(; i != lprPrinters.constEnd(); ++i)
690 widget.printers->addItem((*i).name);
691#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
692 }
693#endif
694
695#ifndef QT_NO_FILESYSTEMMODEL
696 QFileSystemModel *fsm = new QFileSystemModel(widget.filename);
697 fsm->setRootPath(QDir::homePath());
698#if !defined(QT_NO_COMPLETER) && !defined(QT_NO_FILEDIALOG)
699 widget.filename->setCompleter(new QFSCompletor(fsm, widget.filename));
700#endif
701#endif
702 _q_printerChanged(currentPrinterIndex);
703
704 QObject::connect(widget.printers, SIGNAL(currentIndexChanged(int)),
705 parent, SLOT(_q_printerChanged(int)));
706 QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));
707 QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));
708
709 // disable features that QPrinter does not yet support.
710 widget.preview->setVisible(false);
711}
712
713void QUnixPrintWidgetPrivate::updateWidget()
714{
715 const bool printToFile = q == 0 || q->isOptionEnabled(QPrintDialog::PrintToFile);
716 if (printToFile && !filePrintersAdded) {
717 if (widget.printers->count())
718 widget.printers->insertSeparator(widget.printers->count());
719 widget.printers->addItem(QPrintDialog::tr("Print to File (PDF)"));
720 widget.printers->addItem(QPrintDialog::tr("Print to File (Postscript)"));
721 filePrintersAdded = true;
722 }
723 if (!printToFile && filePrintersAdded) {
724 widget.printers->removeItem(widget.printers->count()-1);
725 widget.printers->removeItem(widget.printers->count()-1);
726 if (widget.printers->count())
727 widget.printers->removeItem(widget.printers->count()-1); // remove separator
728 filePrintersAdded = false;
729 }
730 if (printer && filePrintersAdded && printer->printerName().isEmpty()) {
731 if (printer->outputFormat() == QPrinter::PdfFormat)
732 widget.printers->setCurrentIndex(widget.printers->count() - 2);
733 else if (printer->outputFormat() == QPrinter::PostScriptFormat)
734 widget.printers->setCurrentIndex(widget.printers->count() - 1);
735 widget.filename->setEnabled(true);
736 widget.lOutput->setEnabled(true);
737 }
738
739 widget.filename->setVisible(printToFile);
740 widget.lOutput->setVisible(printToFile);
741 widget.fileBrowser->setVisible(printToFile);
742
743 widget.properties->setVisible(q->isOptionEnabled(QAbstractPrintDialog::PrintShowPageSize));
744}
745
746QUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()
747{
748#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
749 delete cups;
750#endif
751}
752
753void QUnixPrintWidgetPrivate::_q_printerChanged(int index)
754{
755 if (index < 0)
756 return;
757 const int printerCount = widget.printers->count();
758 widget.filename->setEnabled(false);
759 widget.lOutput->setEnabled(false);
760
761 if (filePrintersAdded) {
762 Q_ASSERT(index != printerCount - 3); // separator
763 if (index > printerCount - 3) { // PDF or postscript
764 bool pdfPrinter = (index == printerCount - 2);
765 widget.location->setText(QPrintDialog::tr("Local file"));
766 widget.type->setText(QPrintDialog::tr("Write %1 file").arg(pdfPrinter ? QString::fromLatin1("PDF")
767 : QString::fromLatin1("PostScript")));
768 widget.properties->setEnabled(true);
769 widget.filename->setEnabled(true);
770 QString filename = widget.filename->text();
771 QString suffix = QFileInfo(filename).suffix();
772 if (pdfPrinter && suffix == QLatin1String("ps"))
773 filename = filename.replace(QLatin1String(".ps"), QLatin1String(".pdf"));
774 if (!pdfPrinter && suffix == QLatin1String("pdf"))
775 filename = filename.replace(QLatin1String(".pdf"), QLatin1String(".ps"));
776 widget.filename->setText(filename);
777 widget.lOutput->setEnabled(true);
778 if (propertiesDialog)
779 propertiesDialog->selectPdfPsPrinter(printer);
780#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
781 if (optionsPane)
782 optionsPane->selectPrinter(0);
783#endif
784 return;
785 }
786 }
787
788 widget.location->setText(QString());
789#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
790 if (QCUPSSupport::isAvailable()) {
791 cups->setCurrentPrinter(index);
792
793 const cups_option_t *opt = cups->printerOption(QString::fromLatin1("printer-location"));
794 QString location;
795 if (opt)
796 location = QString::fromLocal8Bit(opt->value);
797 widget.location->setText(location);
798
799 cupsPPD = cups->currentPPD();
800 // set printer type line
801 QString type;
802 if (cupsPPD)
803 type = QString::fromLocal8Bit(cupsPPD->manufacturer) + QLatin1String(" - ") + QString::fromLocal8Bit(cupsPPD->modelname);
804 widget.type->setText(type);
805 if (propertiesDialog)
806 propertiesDialog->selectPrinter();
807 if (optionsPane)
808 optionsPane->selectPrinter(cups);
809 } else {
810 if (optionsPane)
811 optionsPane->selectPrinter(0);
812#endif
813 if (lprPrinters.count() > 0) {
814 QString type = lprPrinters.at(index).name + QLatin1String("@") + lprPrinters.at(index).host;
815 if (!lprPrinters.at(index).comment.isEmpty())
816 type += QLatin1String(", ") + lprPrinters.at(index).comment;
817 widget.type->setText(type);
818 if (propertiesDialog)
819 propertiesDialog->selectPrinter();
820 }
821#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
822 }
823#endif
824}
825
826void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
827{
828 optionsPane = pane;
829 if (optionsPane)
830 _q_printerChanged(widget.printers->currentIndex());
831}
832
833void QUnixPrintWidgetPrivate::_q_btnBrowseClicked()
834{
835 const int prevPrinter = widget.printers->currentIndex();
836 widget.printers->setCurrentIndex(widget.printers->count() - 2); // the pdf one
837
838 QString filename = widget.filename->text();
839#ifndef QT_NO_FILEDIALOG
840 filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr("Print To File ..."), filename,
841 QString(), 0, QFileDialog::DontConfirmOverwrite);
842#else
843 filename.clear();
844#endif
845 if (!filename.isEmpty()) {
846 widget.filename->setText(filename);
847 if (filename.endsWith(QString::fromLatin1(".ps"), Qt::CaseInsensitive))
848 widget.printers->setCurrentIndex(widget.printers->count() - 1); // the postscript one
849 }
850 else
851 widget.printers->setCurrentIndex(prevPrinter);
852}
853
854void QUnixPrintWidgetPrivate::applyPrinterProperties(QPrinter *p)
855{
856 if (p == 0)
857 return;
858 printer = p;
859 if (p->outputFileName().isEmpty()) {
860 QString home = QString::fromLocal8Bit(qgetenv("HOME").constData());
861 QString cur = QDir::currentPath();
862 if (home.at(home.length()-1) != QLatin1Char('/'))
863 home += QLatin1Char('/');
864 if (cur.at(cur.length()-1) != QLatin1Char('/'))
865 cur += QLatin1Char('/');
866 if (cur.left(home.length()) != home)
867 cur = home;
868#ifdef Q_WS_X11
869 if (p->docName().isEmpty()) {
870 if (p->outputFormat() == QPrinter::PostScriptFormat)
871 cur += QLatin1String("print.ps");
872 else
873 cur += QLatin1String("print.pdf");
874 } else {
875 QRegExp re(QString::fromLatin1("(.*)\\.\\S+"));
876 if (re.exactMatch(p->docName()))
877 cur += re.cap(1);
878 else
879 cur += p->docName();
880 if (p->outputFormat() == QPrinter::PostScriptFormat)
881 cur += QLatin1String(".ps");
882 else
883 cur += QLatin1String(".pdf");
884 }
885#endif
886 widget.filename->setText(cur);
887 }
888 else
889 widget.filename->setText( p->outputFileName() );
890 QString printer = p->printerName();
891 if (!printer.isEmpty()) {
892 for (int i = 0; i < widget.printers->count(); ++i) {
893 if (widget.printers->itemText(i) == printer) {
894 widget.printers->setCurrentIndex(i);
895 break;
896 }
897 }
898 }
899 // PDF and PS printers are not added to the dialog yet, we'll handle those cases in QUnixPrintWidgetPrivate::updateWidget
900
901 if (propertiesDialog)
902 propertiesDialog->applyPrinterProperties(p);
903}
904
905#ifndef QT_NO_MESSAGEBOX
906bool QUnixPrintWidgetPrivate::checkFields()
907{
908 if (widget.filename->isEnabled()) {
909 QString file = widget.filename->text();
910 QFile f(file);
911 QFileInfo fi(f);
912 bool exists = fi.exists();
913 bool opened = false;
914 if (exists && fi.isDir()) {
915 QMessageBox::warning(q, q->windowTitle(),
916 QPrintDialog::tr("%1 is a directory.\nPlease choose a different file name.").arg(file));
917 return false;
918 } else if ((exists && !fi.isWritable()) || !(opened = f.open(QFile::Append))) {
919 QMessageBox::warning(q, q->windowTitle(),
920 QPrintDialog::tr("File %1 is not writable.\nPlease choose a different file name.").arg(file));
921 return false;
922 } else if (exists) {
923 int ret = QMessageBox::question(q, q->windowTitle(),
924 QPrintDialog::tr("%1 already exists.\nDo you want to overwrite it?").arg(file),
925 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
926 if (ret == QMessageBox::No)
927 return false;
928 }
929 if (opened) {
930 f.close();
931 if (!exists)
932 f.remove();
933 }
934 }
935
936 // Every test passed. Accept the dialog.
937 return true;
938}
939#endif // QT_NO_MESSAGEBOX
940
941void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
942{
943 if (propertiesDialog == 0) {
944 propertiesDialog = new QPrintPropertiesDialog(q);
945 propertiesDialog->setResult(QDialog::Rejected);
946 }
947
948 if (propertiesDialog->result() == QDialog::Rejected) {
949#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
950 propertiesDialog->setCups(cups);
951#endif
952 propertiesDialog->applyPrinterProperties(q->printer());
953
954 if (q->isOptionEnabled(QPrintDialog::PrintToFile)
955 && (widget.printers->currentIndex() > widget.printers->count() - 3)) // PDF or postscript
956 propertiesDialog->selectPdfPsPrinter(q->printer());
957 else
958 propertiesDialog->selectPrinter();
959 }
960 propertiesDialog->exec();
961}
962
963void QUnixPrintWidgetPrivate::setupPrinter()
964{
965 const int printerCount = widget.printers->count();
966 const int index = widget.printers->currentIndex();
967
968 if (filePrintersAdded && index > printerCount - 3) { // PDF or postscript
969 printer->setPrinterName(QString());
970 Q_ASSERT(index != printerCount - 3); // separator
971 if (index == printerCount - 2)
972 printer->setOutputFormat(QPrinter::PdfFormat);
973 else
974 printer->setOutputFormat(QPrinter::PostScriptFormat);
975 QString path = widget.filename->text();
976 if (QDir::isRelativePath(path))
977 path = QDir::homePath() + QDir::separator() + path;
978 printer->setOutputFileName(path);
979 }
980 else {
981 printer->setPrinterName(widget.printers->currentText());
982 printer->setOutputFileName(QString());
983 }
984
985 if (propertiesDialog && propertiesDialog->result() == QDialog::Accepted)
986 propertiesDialog->setupPrinter();
987}
988
989
990/*! \internal
991*/
992QUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)
993 : QWidget(parent), d(new QUnixPrintWidgetPrivate(this))
994{
995 d->applyPrinterProperties(printer);
996}
997
998/*! \internal
999*/
1000QUnixPrintWidget::~QUnixPrintWidget()
1001{
1002 delete d;
1003}
1004
1005/*! \internal
1006
1007 Updates the printer with the states held in the QUnixPrintWidget.
1008*/
1009void QUnixPrintWidget::updatePrinter()
1010{
1011 d->setupPrinter();
1012}
1013
1014#endif
1015
1016////////////////////////////////////////////////////////////////////////////////
1017#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
1018
1019QPPDOptionsModel::QPPDOptionsModel(QCUPSSupport *c, QObject *parent)
1020 : QAbstractItemModel(parent), rootItem(0), cups(c), ppd(c->currentPPD())
1021{
1022 parseItems();
1023}
1024
1025QPPDOptionsModel::~QPPDOptionsModel()
1026{
1027}
1028
1029int QPPDOptionsModel::columnCount(const QModelIndex&) const
1030{
1031 return 2;
1032}
1033
1034int QPPDOptionsModel::rowCount(const QModelIndex& parent) const
1035{
1036 QOptionTreeItem* itm;
1037 if (!parent.isValid())
1038 itm = rootItem;
1039 else
1040 itm = reinterpret_cast<QOptionTreeItem*>(parent.internalPointer());
1041
1042 if (itm->type == QOptionTreeItem::Option)
1043 return 0;
1044
1045 return itm->childItems.count();
1046}
1047
1048QVariant QPPDOptionsModel::data(const QModelIndex& index, int role) const
1049{
1050 switch(role) {
1051 case Qt::FontRole: {
1052 QOptionTreeItem* itm = reinterpret_cast<QOptionTreeItem*>(index.internalPointer());
1053 if (itm && itm->type == QOptionTreeItem::Group){
1054 QFont font = QApplication::font();
1055 font.setBold(true);
1056 return QVariant(font);
1057 }
1058 return QVariant();
1059 }
1060 break;
1061
1062 case Qt::DisplayRole: {
1063 QOptionTreeItem* itm;
1064 if (!index.isValid())
1065 itm = rootItem;
1066 else
1067 itm = reinterpret_cast<QOptionTreeItem*>(index.internalPointer());
1068
1069 if (index.column() == 0)
1070 return cups->unicodeString(itm->description);
1071 else if (itm->type == QOptionTreeItem::Option && itm->selected > -1)
1072 return cups->unicodeString(itm->selDescription);
1073 else
1074 return QVariant();
1075 }
1076 break;
1077
1078 default:
1079 return QVariant();
1080 }
1081 if (role != Qt::DisplayRole)
1082 return QVariant();
1083}
1084
1085QModelIndex QPPDOptionsModel::index(int row, int column, const QModelIndex& parent) const
1086{
1087 QOptionTreeItem* itm;
1088 if (!parent.isValid())
1089 itm = rootItem;
1090 else
1091 itm = reinterpret_cast<QOptionTreeItem*>(parent.internalPointer());
1092
1093 return createIndex(row, column, itm->childItems.at(row));
1094}
1095
1096
1097QModelIndex QPPDOptionsModel::parent(const QModelIndex& index) const
1098{
1099 if (!index.isValid())
1100 return QModelIndex();
1101
1102 QOptionTreeItem* itm = reinterpret_cast<QOptionTreeItem*>(index.internalPointer());
1103
1104 if (itm->parentItem && itm->parentItem != rootItem)
1105 return createIndex(itm->parentItem->index, 0, itm->parentItem);
1106 else
1107 return QModelIndex();
1108}
1109
1110Qt::ItemFlags QPPDOptionsModel::flags(const QModelIndex& index) const
1111{
1112 if (!index.isValid() || reinterpret_cast<QOptionTreeItem*>(index.internalPointer())->type == QOptionTreeItem::Group)
1113 return Qt::ItemIsEnabled;
1114
1115 if (index.column() == 1)
1116 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
1117
1118 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
1119}
1120
1121void QPPDOptionsModel::parseItems()
1122{
1123 emit layoutAboutToBeChanged();
1124 ppd = cups->currentPPD();
1125 delete rootItem;
1126 rootItem = new QOptionTreeItem(QOptionTreeItem::Root, 0, ppd, "Root Item", 0);
1127 parseGroups(rootItem);
1128 emit layoutChanged();
1129}
1130
1131void QPPDOptionsModel::parseGroups(QOptionTreeItem* parent)
1132{
1133 if (parent->type == QOptionTreeItem::Root) {
1134
1135 const ppd_file_t* ppdFile = reinterpret_cast<const ppd_file_t*>(parent->ptr);
1136
1137 if (ppdFile) {
1138 for (int i = 0; i < ppdFile->num_groups; ++i) {
1139 QOptionTreeItem* group = new QOptionTreeItem(QOptionTreeItem::Group, i, &ppdFile->groups[i], ppdFile->groups[i].text, parent);
1140 parent->childItems.append(group);
1141 parseGroups(group); // parse possible subgroups
1142 parseOptions(group); // parse options
1143 }
1144 }
1145 } else if (parent->type == QOptionTreeItem::Group) {
1146
1147 const ppd_group_t* group = reinterpret_cast<const ppd_group_t*>(parent->ptr);
1148
1149 if (group) {
1150 for (int i = 0; i < group->num_subgroups; ++i) {
1151 QOptionTreeItem* subgroup = new QOptionTreeItem(QOptionTreeItem::Group, i, &group->subgroups[i], group->subgroups[i].text, parent);
1152 parent->childItems.append(subgroup);
1153 parseGroups(subgroup); // parse possible subgroups
1154 parseOptions(subgroup); // parse options
1155 }
1156 }
1157 }
1158}
1159
1160void QPPDOptionsModel::parseOptions(QOptionTreeItem* parent)
1161{
1162 const ppd_group_t* group = reinterpret_cast<const ppd_group_t*>(parent->ptr);
1163 for (int i = 0; i < group->num_options; ++i) {
1164 QOptionTreeItem* opt = new QOptionTreeItem(QOptionTreeItem::Option, i, &group->options[i], group->options[i].text, parent);
1165 parent->childItems.append(opt);
1166 parseChoices(opt);
1167 }
1168}
1169
1170void QPPDOptionsModel::parseChoices(QOptionTreeItem* parent)
1171{
1172 const ppd_option_t* option = reinterpret_cast<const ppd_option_t*>(parent->ptr);
1173 bool marked = false;
1174 for (int i = 0; i < option->num_choices; ++i) {
1175 QOptionTreeItem* choice = new QOptionTreeItem(QOptionTreeItem::Choice, i, &option->choices[i], option->choices[i].text, parent);
1176 if (static_cast<int>(option->choices[i].marked) == 1) {
1177 parent->selected = i;
1178 parent->selDescription = option->choices[i].text;
1179 marked = true;
1180 } else if (!marked && qstrcmp(option->choices[i].choice, option->defchoice) == 0) {
1181 parent->selected = i;
1182 parent->selDescription = option->choices[i].text;
1183 }
1184 parent->childItems.append(choice);
1185 }
1186}
1187
1188QVariant QPPDOptionsModel::headerData(int section, Qt::Orientation, int role) const
1189{
1190 if (role != Qt::DisplayRole)
1191 return QVariant();
1192
1193 switch(section){
1194 case 0:
1195 return QVariant(QApplication::translate("QPPDOptionsModel","Name"));
1196 case 1:
1197 return QVariant(QApplication::translate("QPPDOptionsModel","Value"));
1198 default:
1199 return QVariant();
1200 }
1201}
1202
1203////////////////////////////////////////////////////////////////////////////////
1204
1205QWidget* QPPDOptionsEditor::createEditor(QWidget* parent, const QStyleOptionViewItem&, const QModelIndex& index) const
1206{
1207 if (index.column() == 1 && reinterpret_cast<QOptionTreeItem*>(index.internalPointer())->type == QOptionTreeItem::Option)
1208 return new QComboBox(parent);
1209 else
1210 return 0;
1211}
1212
1213void QPPDOptionsEditor::setEditorData(QWidget* editor, const QModelIndex& index) const
1214{
1215 if (index.column() != 1)
1216 return;
1217
1218 QComboBox* cb = static_cast<QComboBox*>(editor);
1219 QOptionTreeItem* itm = reinterpret_cast<QOptionTreeItem*>(index.internalPointer());
1220
1221 if (itm->selected == -1)
1222 cb->addItem(QString());
1223
1224 for (int i = 0; i < itm->childItems.count(); ++i)
1225 cb->addItem(QString::fromLocal8Bit(itm->childItems.at(i)->description));
1226
1227 if (itm->selected > -1)
1228 cb->setCurrentIndex(itm->selected);
1229
1230 connect(cb, SIGNAL(currentIndexChanged(int)), this, SLOT(cbChanged(int)));
1231}
1232
1233void QPPDOptionsEditor::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
1234{
1235 QComboBox* cb = static_cast<QComboBox*>(editor);
1236 QOptionTreeItem* itm = reinterpret_cast<QOptionTreeItem*>(index.internalPointer());
1237
1238 if (itm->selected == cb->currentIndex())
1239 return;
1240
1241 const ppd_option_t* opt = reinterpret_cast<const ppd_option_t*>(itm->ptr);
1242 QPPDOptionsModel* m = static_cast<QPPDOptionsModel*>(model);
1243
1244 if (m->cups->markOption(opt->keyword, opt->choices[cb->currentIndex()].choice) == 0) {
1245 itm->selected = cb->currentIndex();
1246 itm->selDescription = reinterpret_cast<const ppd_option_t*>(itm->ptr)->choices[itm->selected].text;
1247 }
1248}
1249
1250void QPPDOptionsEditor::cbChanged(int)
1251{
1252/*
1253 emit commitData(static_cast<QWidget*>(sender()));
1254*/
1255}
1256
1257#endif
1258
1259QT_END_NAMESPACE
1260
1261#include "moc_qprintdialog.cpp"
1262#include "qprintdialog_unix.moc"
1263#include "qrc_qprintdialog.cpp"
1264
1265#endif // QT_NO_PRINTDIALOG
1266
Note: See TracBrowser for help on using the repository browser.