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