00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <QAbstractScrollArea>
00025 #include <QPrintDialog>
00026 #include <QPrinter>
00027 #include <QToolBar>
00028 #include <QAction>
00029 #include <QTextFormat>
00030 #include <QMouseEvent>
00031 #include <QTextFrame>
00032 #include <QTextDocument>
00033 #include <QAbstractTextDocumentLayout>
00034 #include <QScrollBar>
00035 #include <QPainter>
00036 #include <QDebug>
00037 #include <QPageSetupDialog>
00038 #include <QStatusBar>
00039
00040 #include "printpreview.h"
00041
00042 #ifdef Q_WS_MAC
00043 const QString rsrcPath = ":/images/mac";
00044 #else
00045 const QString rsrcPath = ":/images/win";
00046 #endif
00047
00048 static inline int inchesToPixels(float inches, QPaintDevice *device)
00049 {
00050 return qRound(inches * device->logicalDpiY());
00051 }
00052
00053 static inline qreal mmToInches(double mm)
00054 {
00055 return mm*0.039370147;
00056 }
00057
00058 class PreviewView : public QAbstractScrollArea
00059 {
00060 Q_OBJECT
00061 public:
00062 PreviewView(QTextDocument *document);
00063
00064 inline void updateLayout() { resizeEvent(0); viewport()->update(); }
00065
00066 public slots:
00067 void zoomIn();
00068 void zoomOut();
00069
00070 protected:
00071 virtual void paintEvent(QPaintEvent *e);
00072 virtual void resizeEvent(QResizeEvent *);
00073 virtual void mousePressEvent(QMouseEvent *e);
00074 virtual void mouseMoveEvent(QMouseEvent *e);
00075 virtual void mouseReleaseEvent(QMouseEvent *e);
00076
00077 private:
00078 void paintPage(QPainter *painter, int page);
00079 QTextDocument *doc;
00080 qreal scale;
00081 int interPageSpacing;
00082 QPoint mousePressPos;
00083 QPoint scrollBarValuesOnMousePress;
00084 };
00085
00086 PreviewView::PreviewView(QTextDocument *document)
00087 {
00088 verticalScrollBar()->setSingleStep(20);
00089 horizontalScrollBar()->setSingleStep(20);
00090
00091 viewport()->setBackgroundRole(QPalette::Dark);
00092
00093 doc = document;
00094 scale = 1.0;
00095 interPageSpacing = 30;
00096 }
00097
00098 void PreviewView::zoomIn()
00099 {
00100 scale += 0.2;
00101 resizeEvent(0);
00102 viewport()->update();
00103 }
00104
00105 void PreviewView::zoomOut()
00106 {
00107 scale -= 0.2;
00108 resizeEvent(0);
00109 viewport()->update();
00110 }
00111
00112 void PreviewView::paintEvent(QPaintEvent *)
00113 {
00114 QPainter p(viewport());
00115
00116 p.translate(-horizontalScrollBar()->value(), -verticalScrollBar()->value());
00117 p.translate(interPageSpacing, interPageSpacing);
00118
00119 const int pages = doc->pageCount();
00120 for (int i = 0; i < pages; ++i) {
00121 p.save();
00122 p.scale(scale, scale);
00123
00124 paintPage(&p, i);
00125
00126 p.restore();
00127 p.translate(0, interPageSpacing + doc->pageSize().height() * scale);
00128 }
00129 }
00130
00131 void PreviewView::paintPage(QPainter *painter, int page)
00132 {
00133 const QSizeF pgSize = doc->pageSize();
00134
00135 QColor col(Qt::black);
00136
00137 painter->setPen(col);
00138 painter->setBrush(Qt::white);
00139 painter->drawRect(QRectF(QPointF(0, 0), pgSize));
00140 painter->setBrush(Qt::NoBrush);
00141
00142 col = col.light();
00143 painter->drawLine(QLineF(pgSize.width(), 1, pgSize.width(), pgSize.height() - 1));
00144
00145 col = col.light();
00146 painter->drawLine(QLineF(pgSize.width(), 2, pgSize.width(), pgSize.height() - 2));
00147
00148 QRectF docRect(QPointF(0, page * pgSize.height()), pgSize);
00149 QAbstractTextDocumentLayout::PaintContext ctx;
00150 ctx.clip = docRect;
00151
00152
00153
00154
00155 ctx.palette.setColor(QPalette::Text, Qt::black);
00156
00157 painter->translate(0, - page * pgSize.height());
00158 painter->setClipRect(docRect);
00159 doc->documentLayout()->draw(painter, ctx);
00160 }
00161
00162 void PreviewView::resizeEvent(QResizeEvent *)
00163 {
00164 const QSize viewportSize = viewport()->size();
00165
00166 QSize docSize;
00167 docSize.setWidth(qRound(doc->pageSize().width() * scale + 2 * interPageSpacing));
00168 const int pageCount = doc->pageCount();
00169 docSize.setHeight(qRound(pageCount * doc->pageSize().height() * scale + (pageCount + 1) * interPageSpacing));
00170
00171 horizontalScrollBar()->setRange(0, docSize.width() - viewportSize.width());
00172 horizontalScrollBar()->setPageStep(viewportSize.width());
00173
00174 verticalScrollBar()->setRange(0, docSize.height() - viewportSize.height());
00175 verticalScrollBar()->setPageStep(viewportSize.height());
00176 }
00177
00178 void PreviewView::mousePressEvent(QMouseEvent *e)
00179 {
00180 mousePressPos = e->pos();
00181 scrollBarValuesOnMousePress.rx() = horizontalScrollBar()->value();
00182 scrollBarValuesOnMousePress.ry() = verticalScrollBar()->value();
00183 e->accept();
00184 }
00185
00186 void PreviewView::mouseMoveEvent(QMouseEvent *e)
00187 {
00188 if (mousePressPos.isNull()) {
00189 e->ignore();
00190 return;
00191 }
00192
00193 horizontalScrollBar()->setValue(scrollBarValuesOnMousePress.x() - e->pos().x() + mousePressPos.x());
00194 verticalScrollBar()->setValue(scrollBarValuesOnMousePress.y() - e->pos().y() + mousePressPos.y());
00195 horizontalScrollBar()->update();
00196 verticalScrollBar()->update();
00197 e->accept();
00198 }
00199
00200 void PreviewView::mouseReleaseEvent(QMouseEvent *e)
00201 {
00202 mousePressPos = QPoint();
00203 e->accept();
00204 }
00205
00206 PrintPreview::PrintPreview(const QTextDocument *document, QWidget *parent)
00207 : QMainWindow(parent), printer(QPrinter::HighResolution)
00208 {
00209 setWindowTitle(tr("TextEdit Demo - Print Preview"));
00210
00211 printer.setFullPage(true);
00212 doc = document->clone();
00213
00214 view = new PreviewView(doc);
00215 setCentralWidget(view);
00216 resize(800, 600);
00217
00218 doc->setUseDesignMetrics(true);
00219 doc->documentLayout()->setPaintDevice(view->viewport());
00220
00221
00222 const qreal margin = inchesToPixels(mmToInches(20), this);
00223 QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
00224 fmt.setMargin(margin);
00225 doc->rootFrame()->setFrameFormat(fmt);
00226
00227 setup();
00228
00229 QFont f(doc->defaultFont());
00230 f.setPointSize(10);
00231 doc->setDefaultFont(f);
00232
00233 QToolBar *tb = addToolBar(tr("Print"));
00234 tb->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
00235
00236 QAction *a;
00237 a = new QAction( tr("&Print..."), this);
00238 a->setShortcut(Qt::CTRL + Qt::Key_P);
00239 connect(a, SIGNAL(triggered()), this, SLOT(print()));
00240 tb->addAction(a);
00241
00242 a = new QAction(this);
00243 a->setText(tr("Page Setup..."));
00244 connect(a, SIGNAL(triggered()), this, SLOT(pageSetup()));
00245 tb->addAction(a);
00246
00247 tb->addSeparator();
00248
00249 a = new QAction( tr("Zoom In"), this);
00250 connect(a, SIGNAL(triggered()), view, SLOT(zoomIn()));
00251 tb->addAction(a);
00252
00253 a = new QAction( tr("Zoom Out"), this);
00254 connect(a, SIGNAL(triggered()), view, SLOT(zoomOut()));
00255 tb->addAction(a);
00256
00257 tb->addSeparator();
00258
00259 a = new QAction(this);
00260 a->setText(tr("&Close"));
00261 connect(a, SIGNAL(triggered()), this, SLOT(close()));
00262 tb->addAction(a);
00263
00264 statusBar()->setSizeGripEnabled(true);
00265 }
00266
00267 void PrintPreview::setup()
00268 {
00269 QSizeF page = printer.pageRect().size();
00270 page.setWidth(page.width() * view->logicalDpiX() / printer.logicalDpiX());
00271 page.setHeight(page.height() * view->logicalDpiY() / printer.logicalDpiY());
00272
00273
00274 const qreal margin = inchesToPixels(mmToInches(20), this);
00275 QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
00276 fmt.setMargin(margin);
00277 doc->rootFrame()->setFrameFormat(fmt);
00278
00279 doc->setPageSize(page);
00280 }
00281
00282 PrintPreview::~PrintPreview()
00283 {
00284 delete doc;
00285 }
00286
00287 void PrintPreview::print()
00288 {
00289 QPrintDialog *dlg = new QPrintDialog(&printer, this);
00290 if (dlg->exec() == QDialog::Accepted) {
00291 doc->print(&printer);
00292 }
00293 delete dlg;
00294 }
00295
00296 void PrintPreview::pageSetup()
00297 {
00298 QPageSetupDialog dlg(&printer, this);
00299 if (dlg.exec() == QDialog::Accepted) {
00300 setup();
00301 view->updateLayout();
00302 }
00303 }
00304
00305 #include "printpreview.moc"