| 1 | /****************************************************************************
|
|---|
| 2 | **
|
|---|
| 3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|---|
| 4 | ** Contact: Qt Software Information (qt-info@nokia.com)
|
|---|
| 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 qt-sales@nokia.com.
|
|---|
| 38 | ** $QT_END_LICENSE$
|
|---|
| 39 | **
|
|---|
| 40 | ****************************************************************************/
|
|---|
| 41 |
|
|---|
| 42 | #include "qprintpreviewdialog.h"
|
|---|
| 43 | #include "qprintpreviewwidget.h"
|
|---|
| 44 | #include <private/qprinter_p.h>
|
|---|
| 45 |
|
|---|
| 46 | #include <QtGui/qaction.h>
|
|---|
| 47 | #include <QtGui/qboxlayout.h>
|
|---|
| 48 | #include <QtGui/qcombobox.h>
|
|---|
| 49 | #include <QtGui/qlabel.h>
|
|---|
| 50 | #include <QtGui/qlineedit.h>
|
|---|
| 51 | #include <QtGui/qpagesetupdialog.h>
|
|---|
| 52 | #include <QtGui/qprinter.h>
|
|---|
| 53 | #include <QtGui/qstyle.h>
|
|---|
| 54 | #include <QtGui/qtoolbutton.h>
|
|---|
| 55 | #include <QtGui/qvalidator.h>
|
|---|
| 56 | #include <QtGui/qfiledialog.h>
|
|---|
| 57 | #include <QtCore/QCoreApplication>
|
|---|
| 58 |
|
|---|
| 59 | #include <math.h>
|
|---|
| 60 |
|
|---|
| 61 | #ifndef QT_NO_PRINTPREVIEWDIALOG
|
|---|
| 62 |
|
|---|
| 63 | QT_BEGIN_NAMESPACE
|
|---|
| 64 |
|
|---|
| 65 | namespace {
|
|---|
| 66 | class ZoomFactorValidator : public QDoubleValidator
|
|---|
| 67 | {
|
|---|
| 68 | public:
|
|---|
| 69 | ZoomFactorValidator(QObject* parent)
|
|---|
| 70 | : QDoubleValidator(parent) {}
|
|---|
| 71 | ZoomFactorValidator(qreal bottom, qreal top, int decimals, QObject *parent)
|
|---|
| 72 | : QDoubleValidator(bottom, top, decimals, parent) {}
|
|---|
| 73 |
|
|---|
| 74 | State validate(QString &input, int &pos) const
|
|---|
| 75 | {
|
|---|
| 76 | bool replacePercent = false;
|
|---|
| 77 | if (input.endsWith(QLatin1Char('%'))) {
|
|---|
| 78 | input = input.left(input.length() - 1);
|
|---|
| 79 | replacePercent = true;
|
|---|
| 80 | }
|
|---|
| 81 | State state = QDoubleValidator::validate(input, pos);
|
|---|
| 82 | if (replacePercent)
|
|---|
| 83 | input += QLatin1Char('%');
|
|---|
| 84 | const int num_size = 4;
|
|---|
| 85 | if (state == Intermediate) {
|
|---|
| 86 | int i = input.indexOf(QLocale::system().decimalPoint());
|
|---|
| 87 | if ((i == -1 && input.size() > num_size)
|
|---|
| 88 | || (i != -1 && i > num_size))
|
|---|
| 89 | return Invalid;
|
|---|
| 90 | }
|
|---|
| 91 | return state;
|
|---|
| 92 | }
|
|---|
| 93 | };
|
|---|
| 94 |
|
|---|
| 95 | class LineEdit : public QLineEdit
|
|---|
| 96 | {
|
|---|
| 97 | Q_OBJECT
|
|---|
| 98 | public:
|
|---|
| 99 | LineEdit(QWidget* parent = 0)
|
|---|
| 100 | : QLineEdit(parent)
|
|---|
| 101 | {
|
|---|
| 102 | setContextMenuPolicy(Qt::NoContextMenu);
|
|---|
| 103 | connect(this, SIGNAL(returnPressed()), SLOT(handleReturnPressed()));
|
|---|
| 104 | }
|
|---|
| 105 |
|
|---|
| 106 | protected:
|
|---|
| 107 | void focusInEvent(QFocusEvent *e)
|
|---|
| 108 | {
|
|---|
| 109 | origText = text();
|
|---|
| 110 | QLineEdit::focusInEvent(e);
|
|---|
| 111 | }
|
|---|
| 112 |
|
|---|
| 113 | void focusOutEvent(QFocusEvent *e)
|
|---|
| 114 | {
|
|---|
| 115 | if (isModified() && !hasAcceptableInput())
|
|---|
| 116 | setText(origText);
|
|---|
| 117 | QLineEdit::focusOutEvent(e);
|
|---|
| 118 | }
|
|---|
| 119 |
|
|---|
| 120 | private slots:
|
|---|
| 121 | void handleReturnPressed()
|
|---|
| 122 | {
|
|---|
| 123 | origText = text();
|
|---|
| 124 | }
|
|---|
| 125 |
|
|---|
| 126 | private:
|
|---|
| 127 | QString origText;
|
|---|
| 128 | };
|
|---|
| 129 | } // anonymous namespace
|
|---|
| 130 |
|
|---|
| 131 | class QPrintPreviewDialogPrivate
|
|---|
| 132 | {
|
|---|
| 133 | Q_DECLARE_PUBLIC(QPrintPreviewDialog)
|
|---|
| 134 | public:
|
|---|
| 135 | QPrintPreviewDialogPrivate(QPrintPreviewDialog *q)
|
|---|
| 136 | : q_ptr(q), printDialog(0), ownPrinter(false),
|
|---|
| 137 | initialized(false) {}
|
|---|
| 138 |
|
|---|
| 139 | // private slots
|
|---|
| 140 | void _q_fit(QAction *action);
|
|---|
| 141 | void _q_zoomIn();
|
|---|
| 142 | void _q_zoomOut();
|
|---|
| 143 | void _q_navigate(QAction *action);
|
|---|
| 144 | void _q_setMode(QAction *action);
|
|---|
| 145 | void _q_pageNumEdited();
|
|---|
| 146 | void _q_print();
|
|---|
| 147 | void _q_pageSetup();
|
|---|
| 148 | void _q_previewChanged();
|
|---|
| 149 | void _q_zoomFactorChanged();
|
|---|
| 150 |
|
|---|
| 151 | void init(QPrinter *printer = 0);
|
|---|
| 152 | void populateScene();
|
|---|
| 153 | void layoutPages();
|
|---|
| 154 | void setupActions();
|
|---|
| 155 | void updateNavActions();
|
|---|
| 156 | void setFitting(bool on);
|
|---|
| 157 | bool isFitting();
|
|---|
| 158 | void updatePageNumLabel();
|
|---|
| 159 | void updateZoomFactor();
|
|---|
| 160 |
|
|---|
| 161 | QPrintPreviewDialog *q_ptr;
|
|---|
| 162 | QPrintDialog *printDialog;
|
|---|
| 163 | QPrintPreviewWidget *preview;
|
|---|
| 164 | QPrinter *printer;
|
|---|
| 165 | bool ownPrinter;
|
|---|
| 166 | bool initialized;
|
|---|
| 167 |
|
|---|
| 168 | // widgets:
|
|---|
| 169 | QLineEdit *pageNumEdit;
|
|---|
| 170 | QLabel *pageNumLabel;
|
|---|
| 171 | QComboBox *zoomFactor;
|
|---|
| 172 |
|
|---|
| 173 | // actions:
|
|---|
| 174 | QActionGroup* navGroup;
|
|---|
| 175 | QAction *nextPageAction;
|
|---|
| 176 | QAction *prevPageAction;
|
|---|
| 177 | QAction *firstPageAction;
|
|---|
| 178 | QAction *lastPageAction;
|
|---|
| 179 |
|
|---|
| 180 | QActionGroup* fitGroup;
|
|---|
| 181 | QAction *fitWidthAction;
|
|---|
| 182 | QAction *fitPageAction;
|
|---|
| 183 |
|
|---|
| 184 | QActionGroup* zoomGroup;
|
|---|
| 185 | QAction *zoomInAction;
|
|---|
| 186 | QAction *zoomOutAction;
|
|---|
| 187 |
|
|---|
| 188 | QActionGroup* orientationGroup;
|
|---|
| 189 | QAction *portraitAction;
|
|---|
| 190 | QAction *landscapeAction;
|
|---|
| 191 |
|
|---|
| 192 | QActionGroup* modeGroup;
|
|---|
| 193 | QAction *singleModeAction;
|
|---|
| 194 | QAction *facingModeAction;
|
|---|
| 195 | QAction *overviewModeAction;
|
|---|
| 196 |
|
|---|
| 197 | QActionGroup *printerGroup;
|
|---|
| 198 | QAction *printAction;
|
|---|
| 199 | QAction *pageSetupAction;
|
|---|
| 200 | QAction *closeAction;
|
|---|
| 201 |
|
|---|
| 202 | QPointer<QObject> receiverToDisconnectOnClose;
|
|---|
| 203 | QByteArray memberToDisconnectOnClose;
|
|---|
| 204 | };
|
|---|
| 205 |
|
|---|
| 206 | void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
|
|---|
| 207 | {
|
|---|
| 208 | Q_Q(QPrintPreviewDialog);
|
|---|
| 209 |
|
|---|
| 210 | if (_printer) {
|
|---|
| 211 | preview = new QPrintPreviewWidget(_printer, q);
|
|---|
| 212 | printer = _printer;
|
|---|
| 213 | } else {
|
|---|
| 214 | ownPrinter = true;
|
|---|
| 215 | printer = new QPrinter;
|
|---|
| 216 | preview = new QPrintPreviewWidget(printer, q);
|
|---|
| 217 | }
|
|---|
| 218 | QObject::connect(preview, SIGNAL(paintRequested(QPrinter *)), q, SIGNAL(paintRequested(QPrinter *)));
|
|---|
| 219 | QObject::connect(preview, SIGNAL(previewChanged()), q, SLOT(_q_previewChanged()));
|
|---|
| 220 | setupActions();
|
|---|
| 221 |
|
|---|
| 222 | // Navigation
|
|---|
| 223 | QToolButton* nextPageButton = new QToolButton;
|
|---|
| 224 | nextPageButton->setDefaultAction(nextPageAction);
|
|---|
| 225 | QToolButton* prevPageButton = new QToolButton;
|
|---|
| 226 | prevPageButton->setDefaultAction(prevPageAction);
|
|---|
| 227 | QToolButton* firstPageButton = new QToolButton;
|
|---|
| 228 | firstPageButton->setDefaultAction(firstPageAction);
|
|---|
| 229 | QToolButton* lastPageButton = new QToolButton;
|
|---|
| 230 | lastPageButton->setDefaultAction(lastPageAction);
|
|---|
| 231 |
|
|---|
| 232 | pageNumEdit = new LineEdit;
|
|---|
| 233 | pageNumEdit->setAlignment(Qt::AlignRight);
|
|---|
| 234 | pageNumEdit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
|
|---|
| 235 | pageNumLabel = new QLabel;
|
|---|
| 236 | QObject::connect(pageNumEdit, SIGNAL(editingFinished()), q, SLOT(_q_pageNumEdited()));
|
|---|
| 237 |
|
|---|
| 238 | QToolButton* fitWidthButton = new QToolButton;
|
|---|
| 239 | fitWidthButton->setDefaultAction(fitWidthAction);
|
|---|
| 240 | QToolButton* fitPageButton = new QToolButton;
|
|---|
| 241 | fitPageButton->setDefaultAction(fitPageAction);
|
|---|
| 242 |
|
|---|
| 243 | zoomFactor = new QComboBox;
|
|---|
| 244 | zoomFactor->setEditable(true);
|
|---|
| 245 | zoomFactor->setMinimumContentsLength(7);
|
|---|
| 246 | zoomFactor->setInsertPolicy(QComboBox::NoInsert);
|
|---|
| 247 | LineEdit *zoomEditor = new LineEdit;
|
|---|
| 248 | zoomEditor->setValidator(new ZoomFactorValidator(1, 1000, 1, zoomEditor));
|
|---|
| 249 | zoomFactor->setLineEdit(zoomEditor);
|
|---|
| 250 | static const short factorsX2[] = { 25, 50, 100, 200, 250, 300, 400, 800, 1600 };
|
|---|
| 251 | for (int i = 0; i < int(sizeof(factorsX2) / sizeof(factorsX2[0])); ++i)
|
|---|
| 252 | zoomFactor->addItem(QPrintPreviewDialog::tr("%1%").arg(factorsX2[i] / 2.0));
|
|---|
| 253 | QObject::connect(zoomFactor->lineEdit(), SIGNAL(editingFinished()),
|
|---|
| 254 | q, SLOT(_q_zoomFactorChanged()));
|
|---|
| 255 | QObject::connect(zoomFactor, SIGNAL(currentIndexChanged(int)),
|
|---|
| 256 | q, SLOT(_q_zoomFactorChanged()));
|
|---|
| 257 |
|
|---|
| 258 | QToolButton* zoomInButton = new QToolButton;
|
|---|
| 259 | zoomInButton->setDefaultAction(zoomInAction);
|
|---|
| 260 | zoomInButton->setAutoRepeat(true);
|
|---|
| 261 | zoomInButton->setAutoRepeatInterval(200);
|
|---|
| 262 | zoomInButton->setAutoRepeatDelay(200);
|
|---|
| 263 |
|
|---|
| 264 | QToolButton* zoomOutButton = new QToolButton;
|
|---|
| 265 | zoomOutButton->setDefaultAction(zoomOutAction);
|
|---|
| 266 | zoomOutButton->setAutoRepeat(true);
|
|---|
| 267 | zoomOutButton->setAutoRepeatInterval(200);
|
|---|
| 268 | zoomOutButton->setAutoRepeatDelay(200);
|
|---|
| 269 |
|
|---|
| 270 | //Cannot use the actions' triggered signal here, since it doesnt autorepeat
|
|---|
| 271 | QObject::connect(zoomInButton, SIGNAL(clicked()), q, SLOT(_q_zoomIn()));
|
|---|
| 272 | QObject::connect(zoomOutButton, SIGNAL(clicked()), q, SLOT(_q_zoomOut()));
|
|---|
| 273 |
|
|---|
| 274 | QToolButton* portraitButton = new QToolButton;
|
|---|
| 275 | portraitButton->setDefaultAction(portraitAction);
|
|---|
| 276 | QToolButton* landscapeButton = new QToolButton;
|
|---|
| 277 | landscapeButton->setDefaultAction(landscapeAction);
|
|---|
| 278 |
|
|---|
| 279 | QToolButton* singleModeButton = new QToolButton;
|
|---|
| 280 | singleModeButton->setDefaultAction(singleModeAction);
|
|---|
| 281 | QToolButton* facingModeButton = new QToolButton;
|
|---|
| 282 | facingModeButton->setDefaultAction(facingModeAction);
|
|---|
| 283 | QToolButton* overviewModeButton = new QToolButton;
|
|---|
| 284 | overviewModeButton->setDefaultAction(overviewModeAction);
|
|---|
| 285 |
|
|---|
| 286 | QToolButton *printButton = new QToolButton;
|
|---|
| 287 | printButton->setDefaultAction(printAction);
|
|---|
| 288 | QToolButton *pageSetupButton = new QToolButton;
|
|---|
| 289 | pageSetupButton->setDefaultAction(pageSetupAction);
|
|---|
| 290 | QToolButton *closeButton = new QToolButton;
|
|---|
| 291 | closeButton->setDefaultAction(closeAction);
|
|---|
| 292 |
|
|---|
| 293 | QHBoxLayout* modeLayout = new QHBoxLayout;
|
|---|
| 294 | modeLayout->setSpacing(0);
|
|---|
| 295 | modeLayout->addWidget(singleModeButton);
|
|---|
| 296 | modeLayout->addWidget(facingModeButton);
|
|---|
| 297 | modeLayout->addWidget(overviewModeButton);
|
|---|
| 298 |
|
|---|
| 299 | QHBoxLayout *barLayout = new QHBoxLayout;
|
|---|
| 300 | barLayout->addWidget(fitWidthButton);
|
|---|
| 301 | barLayout->addWidget(fitPageButton);
|
|---|
| 302 | barLayout->addWidget(zoomFactor);
|
|---|
| 303 | barLayout->addWidget(zoomOutButton);
|
|---|
| 304 | barLayout->addWidget(zoomInButton);
|
|---|
| 305 | barLayout->addWidget(portraitButton);
|
|---|
| 306 | barLayout->addWidget(landscapeButton);
|
|---|
| 307 | barLayout->addStretch();
|
|---|
| 308 | barLayout->addWidget(firstPageButton);
|
|---|
| 309 | barLayout->addWidget(prevPageButton);
|
|---|
| 310 | barLayout->addWidget(pageNumEdit);
|
|---|
| 311 | barLayout->addWidget(pageNumLabel);
|
|---|
| 312 | barLayout->addWidget(nextPageButton);
|
|---|
| 313 | barLayout->addWidget(lastPageButton);
|
|---|
| 314 | barLayout->addStretch();
|
|---|
| 315 | barLayout->addLayout(modeLayout);
|
|---|
| 316 | barLayout->addStretch();
|
|---|
| 317 | barLayout->addWidget(pageSetupButton);
|
|---|
| 318 | barLayout->addWidget(printButton);
|
|---|
| 319 | barLayout->addWidget(closeButton);
|
|---|
| 320 |
|
|---|
| 321 | QWidget* buttonBar = new QWidget;
|
|---|
| 322 | buttonBar->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum));
|
|---|
| 323 | barLayout->setMargin(0);
|
|---|
| 324 | buttonBar->setLayout(barLayout);
|
|---|
| 325 |
|
|---|
| 326 | QVBoxLayout *topLayout = new QVBoxLayout;
|
|---|
| 327 | topLayout->addWidget(buttonBar);
|
|---|
| 328 | topLayout->addWidget(preview);
|
|---|
| 329 | q->setLayout(topLayout);
|
|---|
| 330 |
|
|---|
| 331 | QString caption = QCoreApplication::translate("QPrintPreviewDialog", "Print Preview");
|
|---|
| 332 | if (!printer->docName().isEmpty())
|
|---|
| 333 | caption += QString::fromLatin1(": ") + printer->docName();
|
|---|
| 334 | q->setWindowTitle(caption);
|
|---|
| 335 |
|
|---|
| 336 | if (!printer->isValid()
|
|---|
| 337 | #if defined(Q_WS_WIN) || defined(Q_WS_MAC)
|
|---|
| 338 | || printer->outputFormat() != QPrinter::NativeFormat
|
|---|
| 339 | #endif
|
|---|
| 340 | )
|
|---|
| 341 | pageSetupButton->setEnabled(false);
|
|---|
| 342 | }
|
|---|
| 343 |
|
|---|
| 344 | static inline void qt_setupActionIcon(QAction *action, const QLatin1String &name)
|
|---|
| 345 | {
|
|---|
| 346 | QLatin1String imagePrefix(":/trolltech/dialogs/qprintpreviewdialog/images/");
|
|---|
| 347 | QIcon icon;
|
|---|
| 348 | icon.addFile(imagePrefix + name + QLatin1String("-24.png"), QSize(24, 24));
|
|---|
| 349 | icon.addFile(imagePrefix + name + QLatin1String("-32.png"), QSize(32, 32));
|
|---|
| 350 | action->setIcon(icon);
|
|---|
| 351 | }
|
|---|
| 352 |
|
|---|
| 353 | void QPrintPreviewDialogPrivate::setupActions()
|
|---|
| 354 | {
|
|---|
| 355 | Q_Q(QPrintPreviewDialog);
|
|---|
| 356 |
|
|---|
| 357 | // Navigation
|
|---|
| 358 | navGroup = new QActionGroup(q);
|
|---|
| 359 | navGroup->setExclusive(false);
|
|---|
| 360 | nextPageAction = navGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Next page"));
|
|---|
| 361 | prevPageAction = navGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Previous page"));
|
|---|
| 362 | firstPageAction = navGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "First page"));
|
|---|
| 363 | lastPageAction = navGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Last page"));
|
|---|
| 364 | qt_setupActionIcon(nextPageAction, QLatin1String("go-next"));
|
|---|
| 365 | qt_setupActionIcon(prevPageAction, QLatin1String("go-previous"));
|
|---|
| 366 | qt_setupActionIcon(firstPageAction, QLatin1String("go-first"));
|
|---|
| 367 | qt_setupActionIcon(lastPageAction, QLatin1String("go-last"));
|
|---|
| 368 | QObject::connect(navGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_navigate(QAction*)));
|
|---|
| 369 |
|
|---|
| 370 |
|
|---|
| 371 | fitGroup = new QActionGroup(q);
|
|---|
| 372 | fitWidthAction = fitGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Fit width"));
|
|---|
| 373 | fitPageAction = fitGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Fit page"));
|
|---|
| 374 | fitWidthAction->setObjectName(QLatin1String("fitWidthAction"));
|
|---|
| 375 | fitPageAction->setObjectName(QLatin1String("fitPageAction"));
|
|---|
| 376 | fitWidthAction->setCheckable(true);
|
|---|
| 377 | fitPageAction->setCheckable(true);
|
|---|
| 378 | qt_setupActionIcon(fitWidthAction, QLatin1String("fit-width"));
|
|---|
| 379 | qt_setupActionIcon(fitPageAction, QLatin1String("fit-page"));
|
|---|
| 380 | QObject::connect(fitGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_fit(QAction*)));
|
|---|
| 381 |
|
|---|
| 382 | // Zoom
|
|---|
| 383 | zoomGroup = new QActionGroup(q);
|
|---|
| 384 | zoomInAction = zoomGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Zoom in"));
|
|---|
| 385 | zoomOutAction = zoomGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Zoom out"));
|
|---|
| 386 | qt_setupActionIcon(zoomInAction, QLatin1String("zoom-in"));
|
|---|
| 387 | qt_setupActionIcon(zoomOutAction, QLatin1String("zoom-out"));
|
|---|
| 388 |
|
|---|
| 389 | // Portrait/Landscape
|
|---|
| 390 | orientationGroup = new QActionGroup(q);
|
|---|
| 391 | portraitAction = orientationGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Portrait"));
|
|---|
| 392 | landscapeAction = orientationGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Landscape"));
|
|---|
| 393 | portraitAction->setCheckable(true);
|
|---|
| 394 | landscapeAction->setCheckable(true);
|
|---|
| 395 | qt_setupActionIcon(portraitAction, QLatin1String("layout-portrait"));
|
|---|
| 396 | qt_setupActionIcon(landscapeAction, QLatin1String("layout-landscape"));
|
|---|
| 397 | QObject::connect(portraitAction, SIGNAL(triggered(bool)), preview, SLOT(setPortraitOrientation()));
|
|---|
| 398 | QObject::connect(landscapeAction, SIGNAL(triggered(bool)), preview, SLOT(setLandscapeOrientation()));
|
|---|
| 399 |
|
|---|
| 400 | // Display mode
|
|---|
| 401 | modeGroup = new QActionGroup(q);
|
|---|
| 402 | singleModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show single page"));
|
|---|
| 403 | facingModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show facing pages"));
|
|---|
| 404 | overviewModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show overview of all pages"));
|
|---|
| 405 | qt_setupActionIcon(singleModeAction, QLatin1String("view-page-one"));
|
|---|
| 406 | qt_setupActionIcon(facingModeAction, QLatin1String("view-page-sided"));
|
|---|
| 407 | qt_setupActionIcon(overviewModeAction, QLatin1String("view-page-multi"));
|
|---|
| 408 | singleModeAction->setObjectName(QLatin1String("singleModeAction"));
|
|---|
| 409 | facingModeAction->setObjectName(QLatin1String("facingModeAction"));
|
|---|
| 410 | overviewModeAction->setObjectName(QLatin1String("overviewModeAction"));
|
|---|
| 411 |
|
|---|
| 412 | singleModeAction->setCheckable(true);
|
|---|
| 413 | facingModeAction->setCheckable(true);
|
|---|
| 414 | overviewModeAction->setCheckable(true);
|
|---|
| 415 | QObject::connect(modeGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_setMode(QAction*)));
|
|---|
| 416 |
|
|---|
| 417 | // Print
|
|---|
| 418 | printerGroup = new QActionGroup(q);
|
|---|
| 419 | printAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Print"));
|
|---|
| 420 | pageSetupAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Page setup"));
|
|---|
| 421 | closeAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Close"));
|
|---|
| 422 | qt_setupActionIcon(printAction, QLatin1String("print"));
|
|---|
| 423 | qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup"));
|
|---|
| 424 | QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print()));
|
|---|
| 425 | QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup()));
|
|---|
| 426 | QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(reject()));
|
|---|
| 427 |
|
|---|
| 428 | // Initial state:
|
|---|
| 429 | fitPageAction->setChecked(true);
|
|---|
| 430 | singleModeAction->setChecked(true);
|
|---|
| 431 | if (preview->orientation() == QPrinter::Portrait)
|
|---|
| 432 | portraitAction->setChecked(true);
|
|---|
| 433 | else
|
|---|
| 434 | landscapeAction->setChecked(true);
|
|---|
| 435 | }
|
|---|
| 436 |
|
|---|
| 437 |
|
|---|
| 438 | bool QPrintPreviewDialogPrivate::isFitting()
|
|---|
| 439 | {
|
|---|
| 440 | return (fitGroup->isExclusive()
|
|---|
| 441 | && (fitWidthAction->isChecked() || fitPageAction->isChecked()));
|
|---|
| 442 | }
|
|---|
| 443 |
|
|---|
| 444 |
|
|---|
| 445 | void QPrintPreviewDialogPrivate::setFitting(bool on)
|
|---|
| 446 | {
|
|---|
| 447 | if (isFitting() == on)
|
|---|
| 448 | return;
|
|---|
| 449 | fitGroup->setExclusive(on);
|
|---|
| 450 | if (on) {
|
|---|
| 451 | QAction* action = fitWidthAction->isChecked() ? fitWidthAction : fitPageAction;
|
|---|
| 452 | action->setChecked(true);
|
|---|
| 453 | if (fitGroup->checkedAction() != action) {
|
|---|
| 454 | // work around exclusitivity problem
|
|---|
| 455 | fitGroup->removeAction(action);
|
|---|
| 456 | fitGroup->addAction(action);
|
|---|
| 457 | }
|
|---|
| 458 | } else {
|
|---|
| 459 | fitWidthAction->setChecked(false);
|
|---|
| 460 | fitPageAction->setChecked(false);
|
|---|
| 461 | }
|
|---|
| 462 | }
|
|---|
| 463 |
|
|---|
| 464 | void QPrintPreviewDialogPrivate::updateNavActions()
|
|---|
| 465 | {
|
|---|
| 466 | int curPage = preview->currentPage();
|
|---|
| 467 | int numPages = preview->numPages();
|
|---|
| 468 | nextPageAction->setEnabled(curPage < numPages);
|
|---|
| 469 | prevPageAction->setEnabled(curPage > 1);
|
|---|
| 470 | firstPageAction->setEnabled(curPage > 1);
|
|---|
| 471 | lastPageAction->setEnabled(curPage < numPages);
|
|---|
| 472 | pageNumEdit->setText(QString::number(curPage));
|
|---|
| 473 | }
|
|---|
| 474 |
|
|---|
| 475 | void QPrintPreviewDialogPrivate::updatePageNumLabel()
|
|---|
| 476 | {
|
|---|
| 477 | Q_Q(QPrintPreviewDialog);
|
|---|
| 478 |
|
|---|
| 479 | int numPages = preview->numPages();
|
|---|
| 480 | int maxChars = QString::number(numPages).length();
|
|---|
| 481 | pageNumLabel->setText(QString(QLatin1String("/ %1")).arg(numPages));
|
|---|
| 482 | int cyphersWidth = q->fontMetrics().width(QString().fill(QLatin1Char('8'), maxChars));
|
|---|
| 483 | int maxWidth = pageNumEdit->minimumSizeHint().width() + cyphersWidth;
|
|---|
| 484 | pageNumEdit->setMinimumWidth(maxWidth);
|
|---|
| 485 | pageNumEdit->setMaximumWidth(maxWidth);
|
|---|
| 486 | pageNumEdit->setValidator(new QIntValidator(1, numPages, pageNumEdit));
|
|---|
| 487 | // any old one will be deleted later along with its parent pageNumEdit
|
|---|
| 488 | }
|
|---|
| 489 |
|
|---|
| 490 | void QPrintPreviewDialogPrivate::updateZoomFactor()
|
|---|
| 491 | {
|
|---|
| 492 | zoomFactor->lineEdit()->setText(QString().sprintf("%.1f%%", preview->zoomFactor()*100));
|
|---|
| 493 | }
|
|---|
| 494 |
|
|---|
| 495 | void QPrintPreviewDialogPrivate::_q_fit(QAction* action)
|
|---|
| 496 | {
|
|---|
| 497 | setFitting(true);
|
|---|
| 498 | if (action == fitPageAction)
|
|---|
| 499 | preview->fitInView();
|
|---|
| 500 | else
|
|---|
| 501 | preview->fitToWidth();
|
|---|
| 502 | }
|
|---|
| 503 |
|
|---|
| 504 | void QPrintPreviewDialogPrivate::_q_zoomIn()
|
|---|
| 505 | {
|
|---|
| 506 | setFitting(false);
|
|---|
| 507 | preview->zoomIn();
|
|---|
| 508 | updateZoomFactor();
|
|---|
| 509 | }
|
|---|
| 510 |
|
|---|
| 511 | void QPrintPreviewDialogPrivate::_q_zoomOut()
|
|---|
| 512 | {
|
|---|
| 513 | setFitting(false);
|
|---|
| 514 | preview->zoomOut();
|
|---|
| 515 | updateZoomFactor();
|
|---|
| 516 | }
|
|---|
| 517 |
|
|---|
| 518 | void QPrintPreviewDialogPrivate::_q_pageNumEdited()
|
|---|
| 519 | {
|
|---|
| 520 | bool ok = false;
|
|---|
| 521 | int res = pageNumEdit->text().toInt(&ok);
|
|---|
| 522 | if (ok)
|
|---|
| 523 | preview->setCurrentPage(res);
|
|---|
| 524 | }
|
|---|
| 525 |
|
|---|
| 526 | void QPrintPreviewDialogPrivate::_q_navigate(QAction* action)
|
|---|
| 527 | {
|
|---|
| 528 | int curPage = preview->currentPage();
|
|---|
| 529 | if (action == prevPageAction)
|
|---|
| 530 | preview->setCurrentPage(curPage - 1);
|
|---|
| 531 | else if (action == nextPageAction)
|
|---|
| 532 | preview->setCurrentPage(curPage + 1);
|
|---|
| 533 | else if (action == firstPageAction)
|
|---|
| 534 | preview->setCurrentPage(1);
|
|---|
| 535 | else if (action == lastPageAction)
|
|---|
| 536 | preview->setCurrentPage(preview->numPages());
|
|---|
| 537 | updateNavActions();
|
|---|
| 538 | }
|
|---|
| 539 |
|
|---|
| 540 | void QPrintPreviewDialogPrivate::_q_setMode(QAction* action)
|
|---|
| 541 | {
|
|---|
| 542 | if (action == overviewModeAction) {
|
|---|
| 543 | preview->setViewMode(QPrintPreviewWidget::AllPagesView);
|
|---|
| 544 | setFitting(false);
|
|---|
| 545 | fitGroup->setEnabled(false);
|
|---|
| 546 | navGroup->setEnabled(false);
|
|---|
| 547 | pageNumEdit->setEnabled(false);
|
|---|
| 548 | pageNumLabel->setEnabled(false);
|
|---|
| 549 | } else if (action == facingModeAction) {
|
|---|
| 550 | preview->setViewMode(QPrintPreviewWidget::FacingPagesView);
|
|---|
| 551 | } else {
|
|---|
| 552 | preview->setViewMode(QPrintPreviewWidget::SinglePageView);
|
|---|
| 553 | }
|
|---|
| 554 | if (action == facingModeAction || action == singleModeAction) {
|
|---|
| 555 | fitGroup->setEnabled(true);
|
|---|
| 556 | navGroup->setEnabled(true);
|
|---|
| 557 | pageNumEdit->setEnabled(true);
|
|---|
| 558 | pageNumLabel->setEnabled(true);
|
|---|
| 559 | setFitting(true);
|
|---|
| 560 | }
|
|---|
| 561 | }
|
|---|
| 562 |
|
|---|
| 563 | void QPrintPreviewDialogPrivate::_q_print()
|
|---|
| 564 | {
|
|---|
| 565 | Q_Q(QPrintPreviewDialog);
|
|---|
| 566 |
|
|---|
| 567 | #if defined(Q_WS_WIN) || defined(Q_WS_MAC)
|
|---|
| 568 | if (printer->outputFormat() != QPrinter::NativeFormat) {
|
|---|
| 569 | QString title;
|
|---|
| 570 | QString suffix;
|
|---|
| 571 | if (printer->outputFormat() == QPrinter::PdfFormat) {
|
|---|
| 572 | title = QCoreApplication::translate("QPrintPreviewDialog", "Export to PDF");
|
|---|
| 573 | suffix = QLatin1String(".pdf");
|
|---|
| 574 | } else {
|
|---|
| 575 | title = QCoreApplication::translate("QPrintPreviewDialog", "Export to PostScript");
|
|---|
| 576 | suffix = QLatin1String(".ps");
|
|---|
| 577 | }
|
|---|
| 578 | QString fileName = QFileDialog::getSaveFileName(q, title, printer->outputFileName(),
|
|---|
| 579 | QLatin1String("*") + suffix);
|
|---|
| 580 | if (!fileName.isEmpty()) {
|
|---|
| 581 | if (QFileInfo(fileName).suffix().isEmpty())
|
|---|
| 582 | fileName.append(suffix);
|
|---|
| 583 | printer->setOutputFileName(fileName);
|
|---|
| 584 | }
|
|---|
| 585 | if (!printer->outputFileName().isEmpty())
|
|---|
| 586 | preview->print();
|
|---|
| 587 | q->accept();
|
|---|
| 588 | return;
|
|---|
| 589 | }
|
|---|
| 590 | #endif
|
|---|
| 591 |
|
|---|
| 592 | if (!printDialog)
|
|---|
| 593 | printDialog = new QPrintDialog(printer, q);
|
|---|
| 594 | if (printDialog->exec() == QDialog::Accepted) {
|
|---|
| 595 | preview->print();
|
|---|
| 596 | q->accept();
|
|---|
| 597 | }
|
|---|
| 598 | }
|
|---|
| 599 |
|
|---|
| 600 | void QPrintPreviewDialogPrivate::_q_pageSetup()
|
|---|
| 601 | {
|
|---|
| 602 | Q_Q(QPrintPreviewDialog);
|
|---|
| 603 |
|
|---|
| 604 | QPageSetupDialog pageSetup(printer, q);
|
|---|
| 605 | if (pageSetup.exec() == QDialog::Accepted) {
|
|---|
| 606 | // update possible orientation changes
|
|---|
| 607 | if (preview->orientation() == QPrinter::Portrait) {
|
|---|
| 608 | portraitAction->setChecked(true);
|
|---|
| 609 | preview->setPortraitOrientation();
|
|---|
| 610 | }else {
|
|---|
| 611 | landscapeAction->setChecked(true);
|
|---|
| 612 | preview->setLandscapeOrientation();
|
|---|
| 613 | }
|
|---|
| 614 | }
|
|---|
| 615 | }
|
|---|
| 616 |
|
|---|
| 617 | void QPrintPreviewDialogPrivate::_q_previewChanged()
|
|---|
| 618 | {
|
|---|
| 619 | updateNavActions();
|
|---|
| 620 | updatePageNumLabel();
|
|---|
| 621 | updateZoomFactor();
|
|---|
| 622 | }
|
|---|
| 623 |
|
|---|
| 624 | void QPrintPreviewDialogPrivate::_q_zoomFactorChanged()
|
|---|
| 625 | {
|
|---|
| 626 | QString text = zoomFactor->lineEdit()->text();
|
|---|
| 627 | bool ok;
|
|---|
| 628 | qreal factor = text.remove(QLatin1Char('%')).toFloat(&ok);
|
|---|
| 629 | factor = qMax(qreal(1.0), qMin(qreal(1000.0), factor));
|
|---|
| 630 | if (ok) {
|
|---|
| 631 | preview->setZoomFactor(factor/100.0);
|
|---|
| 632 | zoomFactor->setEditText(QString(QLatin1String("%1%")).arg(factor));
|
|---|
| 633 | setFitting(false);
|
|---|
| 634 | }
|
|---|
| 635 | }
|
|---|
| 636 |
|
|---|
| 637 | ///////////////////////////////////////////////////////////////////////////
|
|---|
| 638 |
|
|---|
| 639 | /*!
|
|---|
| 640 | \class QPrintPreviewDialog
|
|---|
| 641 | \since 4.4
|
|---|
| 642 |
|
|---|
| 643 | \brief The QPrintPreviewDialog class provides a dialog for
|
|---|
| 644 | previewing and configuring page layouts for printer output.
|
|---|
| 645 |
|
|---|
| 646 | Using QPrintPreviewDialog in your existing application is
|
|---|
| 647 | straightforward:
|
|---|
| 648 |
|
|---|
| 649 | \list 1
|
|---|
| 650 | \o Create the QPrintPreviewDialog.
|
|---|
| 651 |
|
|---|
| 652 | You can construct a QPrintPreviewDialog with an existing QPrinter
|
|---|
| 653 | object, or you can have QPrintPreviewDialog create one for you,
|
|---|
| 654 | which will be the system default printer.
|
|---|
| 655 |
|
|---|
| 656 | \o Connect the paintRequested() signal to a slot.
|
|---|
| 657 |
|
|---|
| 658 | When the dialog needs to generate a set of preview pages, the
|
|---|
| 659 | paintRequested() signal will be emitted. You can use the exact
|
|---|
| 660 | same code for the actual printing as for having the preview
|
|---|
| 661 | generated, including calling QPrinter::newPage() to start a new
|
|---|
| 662 | page in the preview. Connect a slot to the paintRequested()
|
|---|
| 663 | signal, where you draw onto the QPrinter object that is passed
|
|---|
| 664 | into the slot.
|
|---|
| 665 |
|
|---|
| 666 | \o Call exec().
|
|---|
| 667 |
|
|---|
| 668 | Call QPrintPreviewDialog::exec() to show the preview dialog.
|
|---|
| 669 | \endlist
|
|---|
| 670 |
|
|---|
| 671 |
|
|---|
| 672 | \sa QPrinter, QPrintDialog, QPageSetupDialog, QPrintPreviewWidget
|
|---|
| 673 | */
|
|---|
| 674 |
|
|---|
| 675 | /*!
|
|---|
| 676 | Constructs a QPrintPreviewDialog based on \a printer and with \a
|
|---|
| 677 | parent as the parent widget. The widget flags \a flags are passed on
|
|---|
| 678 | to the QWidget constructor.
|
|---|
| 679 |
|
|---|
| 680 | \sa QWidget::setWindowFlags()
|
|---|
| 681 | */
|
|---|
| 682 | QPrintPreviewDialog::QPrintPreviewDialog(QPrinter* printer, QWidget *parent, Qt::WindowFlags flags)
|
|---|
| 683 | : QDialog(parent, flags), d_ptr(new QPrintPreviewDialogPrivate(this))
|
|---|
| 684 | {
|
|---|
| 685 | Q_D(QPrintPreviewDialog);
|
|---|
| 686 | d->init(printer);
|
|---|
| 687 | }
|
|---|
| 688 |
|
|---|
| 689 | /*!
|
|---|
| 690 | \overload
|
|---|
| 691 | \fn QPrintPreviewDialog::QPrintPreviewDialog(QWidget *parent, Qt::WindowFlags flags)
|
|---|
| 692 |
|
|---|
| 693 | This will create an internal QPrinter object, which will use the
|
|---|
| 694 | system default printer.
|
|---|
| 695 | */
|
|---|
| 696 | QPrintPreviewDialog::QPrintPreviewDialog(QWidget *parent, Qt::WindowFlags f)
|
|---|
| 697 | : QDialog(parent, f), d_ptr(new QPrintPreviewDialogPrivate(this))
|
|---|
| 698 | {
|
|---|
| 699 | Q_D(QPrintPreviewDialog);
|
|---|
| 700 | d->init();
|
|---|
| 701 | }
|
|---|
| 702 |
|
|---|
| 703 | /*!
|
|---|
| 704 | Destroys the QPrintPreviewDialog.
|
|---|
| 705 | */
|
|---|
| 706 | QPrintPreviewDialog::~QPrintPreviewDialog()
|
|---|
| 707 | {
|
|---|
| 708 | Q_D(QPrintPreviewDialog);
|
|---|
| 709 | if (d->ownPrinter)
|
|---|
| 710 | delete d->printer;
|
|---|
| 711 | delete d->printDialog;
|
|---|
| 712 | delete d_ptr;
|
|---|
| 713 | }
|
|---|
| 714 |
|
|---|
| 715 | /*!
|
|---|
| 716 | \reimp
|
|---|
| 717 | */
|
|---|
| 718 | void QPrintPreviewDialog::setVisible(bool visible)
|
|---|
| 719 | {
|
|---|
| 720 | Q_D(QPrintPreviewDialog);
|
|---|
| 721 | // this will make the dialog get a decent default size
|
|---|
| 722 | if (visible && !d->initialized) {
|
|---|
| 723 | d->preview->updatePreview();
|
|---|
| 724 | d->initialized = true;
|
|---|
| 725 | }
|
|---|
| 726 | QDialog::setVisible(visible);
|
|---|
| 727 | }
|
|---|
| 728 |
|
|---|
| 729 | /*!
|
|---|
| 730 | \reimp
|
|---|
| 731 | */
|
|---|
| 732 | void QPrintPreviewDialog::done(int result)
|
|---|
| 733 | {
|
|---|
| 734 | Q_D(QPrintPreviewDialog);
|
|---|
| 735 | QDialog::done(result);
|
|---|
| 736 | if (d->receiverToDisconnectOnClose) {
|
|---|
| 737 | disconnect(this, SIGNAL(finished(int)),
|
|---|
| 738 | d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
|
|---|
| 739 | d->receiverToDisconnectOnClose = 0;
|
|---|
| 740 | }
|
|---|
| 741 | d->memberToDisconnectOnClose.clear();
|
|---|
| 742 | }
|
|---|
| 743 |
|
|---|
| 744 | /*!
|
|---|
| 745 | \overload
|
|---|
| 746 | \since 4.5
|
|---|
| 747 |
|
|---|
| 748 | Opens the dialog and connects its finished(int) signal to the slot specified
|
|---|
| 749 | by \a receiver and \a member.
|
|---|
| 750 |
|
|---|
| 751 | The signal will be disconnected from the slot when the dialog is closed.
|
|---|
| 752 | */
|
|---|
| 753 | void QPrintPreviewDialog::open(QObject *receiver, const char *member)
|
|---|
| 754 | {
|
|---|
| 755 | Q_D(QPrintPreviewDialog);
|
|---|
| 756 | // the int parameter isn't very useful here; we could just as well connect
|
|---|
| 757 | // to reject(), but this feels less robust somehow
|
|---|
| 758 | connect(this, SIGNAL(finished(int)), receiver, member);
|
|---|
| 759 | d->receiverToDisconnectOnClose = receiver;
|
|---|
| 760 | d->memberToDisconnectOnClose = member;
|
|---|
| 761 | QDialog::open();
|
|---|
| 762 | }
|
|---|
| 763 |
|
|---|
| 764 | /*!
|
|---|
| 765 | Returns a pointer to the QPrinter object this dialog is currently
|
|---|
| 766 | operating on.
|
|---|
| 767 | */
|
|---|
| 768 | QPrinter *QPrintPreviewDialog::printer()
|
|---|
| 769 | {
|
|---|
| 770 | Q_D(QPrintPreviewDialog);
|
|---|
| 771 | return d->printer;
|
|---|
| 772 | }
|
|---|
| 773 |
|
|---|
| 774 | /*!
|
|---|
| 775 | \fn void QPrintPreviewDialog::paintRequested(QPrinter *printer)
|
|---|
| 776 |
|
|---|
| 777 | This signal is emitted when the QPrintPreviewDialog needs to generate
|
|---|
| 778 | a set of preview pages.
|
|---|
| 779 |
|
|---|
| 780 | The \a printer instance supplied is the paint device onto which you should
|
|---|
| 781 | paint the contents of each page, using the QPrinter instance in the same way
|
|---|
| 782 | as you would when printing directly.
|
|---|
| 783 | */
|
|---|
| 784 |
|
|---|
| 785 |
|
|---|
| 786 | QT_END_NAMESPACE
|
|---|
| 787 |
|
|---|
| 788 | #include "moc_qprintpreviewdialog.cpp"
|
|---|
| 789 | #include "qprintpreviewdialog.moc"
|
|---|
| 790 |
|
|---|
| 791 | #endif // QT_NO_PRINTPREVIEWDIALOG
|
|---|
| 792 |
|
|---|
| 793 |
|
|---|