diff options
author | Thomas Zander <thomas.zander@trolltech.com> | 2009-05-18 17:24:49 +0200 |
---|---|---|
committer | Thomas Zander <thomas.zander@trolltech.com> | 2009-05-18 17:32:26 +0200 |
commit | 526d5a474a6474ecae7b186215fab12446b24e05 (patch) | |
tree | 046a0e45bd08bb0eb1c135133f331e27839339cb | |
parent | b69219e9aa4f44e39d464a9d803eed11035834aa (diff) |
Transplant the example code into a new qprintertableview class
-rw-r--r-- | examples/spreadsheet/spreadsheet.cpp | 120 | ||||
-rw-r--r-- | src/qgraphicstableview.h | 1 | ||||
-rw-r--r-- | src/qprintertableview.cpp | 366 | ||||
-rw-r--r-- | src/qprintertableview.h | 74 | ||||
-rw-r--r-- | src/qprintertableview_p.h | 77 | ||||
-rw-r--r-- | src/src.pro | 3 |
6 files changed, 530 insertions, 111 deletions
diff --git a/examples/spreadsheet/spreadsheet.cpp b/examples/spreadsheet/spreadsheet.cpp index 65fb574..ecd7b2c 100644 --- a/examples/spreadsheet/spreadsheet.cpp +++ b/examples/spreadsheet/spreadsheet.cpp @@ -25,15 +25,15 @@ #include <qtabledefaultmodel.h> #include <qtablecontroller.h> #include <qgraphicstableview.h> +#include <qprintertableview.h> #include <qtableselectionmanager.h> #include <QDebug> #include <QLabel> +#include <QPrintDialog> #include <QPrinter> #include <QGraphicsWidget> -// #define DEBUG_TABLES - SpreadSheet::SpreadSheet(QWidget *parent) : QMainWindow(parent) { @@ -67,116 +67,14 @@ extern int qt_defaultDpiX(); void SpreadSheet::print() { - QPrinter printer; - printer.setOutputFileName("printedTable.pdf"); - printer.setPaperSize(QSizeF(106, 80), QPrinter::Millimeter); - printer.setResolution(600); - QPainter painter(&printer); - - const qreal scaleX = printer.logicalDpiX() / (qreal) qt_defaultDpiX(); - const qreal scaleY = printer.logicalDpiY() / (qreal) qt_defaultDpiY(); - painter.scale(scaleX, scaleY); - - const QRect rect = printer.pageRect(); - const QSizeF visibleSize(rect.width() / scaleX, rect.height() / scaleY); - - QtTableController *controller = mainwindow.table->controller(); - Q_ASSERT(controller); - QtGraphicsTableView *view = controller->view(); - Q_ASSERT(view); - QGraphicsScene *scene = view->scene(); - Q_ASSERT(scene); - - const int oldFirstRow = view->firstRow(); - const int oldFirstColumn = view->firstColumn(); - const QRectF oldGeometry = view->geometry(); - const qreal oldHorizontalOffset = view->horizontalOffset(); - view->setGeometry(0, 0, visibleSize.width(), visibleSize.height()); - view->setHorizontalOffset(0); - - int row = 0; - int column; - bool first = true; - qreal offsetInColumn = 0; // for those columns too wide and thus split over more than one page - while (row < controller->model()->rowCount()) { - column = 0; - view->setFirstRow(row); - qreal height = visibleSize.height(); - while (true) { - const qreal rowHeight = controller->view()->rowHeight(row); - if (height - rowHeight < 0) - break; - if (row >= controller->model()->rowCount()) - break; - ++row; - height -= rowHeight; - } - while (column < controller->model()->columnCount()) { - if (!first) - printer.newPage(); - first = false; - view->setFirstColumn(column); - view->setHorizontalOffset(offsetInColumn); - - qreal width = visibleSize.width(); - while (true) { - const qreal columnWidth = controller->view()->columnWidth(column); - if (width == visibleSize.width() && columnWidth - offsetInColumn > visibleSize.width()) { - // the column doesn't fit on a page. Lets split it. - offsetInColumn += visibleSize.width(); - break; - } else if (offsetInColumn > 0) { // we still have a part of a split column to print! - width -= columnWidth - offsetInColumn; - offsetInColumn = 0; - ++column; - continue; - } - - if (width - columnWidth + offsetInColumn < 0) { - break; - } - if (column >= controller->model()->columnCount()) - break; - ++column; - width -= columnWidth; - } -#ifdef DEBUG_TABLES - painter.setPen(QPen(QColor(Qt::green))); - painter.drawRect(QRectF(0, 0, visibleSize.width() - width, visibleSize.height() - height)); -#endif - view->doLayout(); - // find and paint children which are the cells - QList<QGraphicsItem*> items = scene->items(view->rect()); - QList<QGraphicsItem*>::Iterator iter = items.begin(); - for (;iter != items.end(); ++iter) { - QGraphicsItem *parent = *iter; - while (parent != view && parent != 0) - parent = parent->parentItem(); - if (parent == 0) - continue; - if (!(*iter)->isVisible()) - continue; - painter.save(); - painter.translate((*iter)->mapToItem(view, QPointF())); -#ifdef DEBUG_TABLES - QGraphicsWidget *w = dynamic_cast<QGraphicsWidget*>(*iter); - if (w) { - painter.save(); - painter.setPen(QPen(QColor(Qt::red))); - painter.drawRect(QRectF(QPointF(), w->size())); - painter.restore(); - } -#endif - (*iter)->paint(&painter, 0); - painter.restore(); - } - } + QtPrinterTableView printerView(mainwindow.table->defaultModel(), + mainwindow.table->controller()->verticalHeader(), + mainwindow.table->controller()->horizontalHeader()); + + QPrintDialog dialog(printerView.printer()); + if (dialog.exec() == QPrintDialog::Accepted) { + printerView.print(); } - // restore previous settings. - view->setFirstRow(oldFirstRow); - view->setFirstColumn(oldFirstColumn); - view->setGeometry(oldGeometry); - view->setHorizontalOffset(oldHorizontalOffset); } void SpreadSheet::updateStatus(int row, int column) diff --git a/src/qgraphicstableview.h b/src/qgraphicstableview.h index cef611c..2a9e03e 100644 --- a/src/qgraphicstableview.h +++ b/src/qgraphicstableview.h @@ -156,6 +156,7 @@ protected: QtGraphicsTableView(QtGraphicsTableViewPrivate&, QGraphicsWidget *parent = 0, Qt::WindowFlags wFlags = 0); virtual bool event(QEvent *event); + friend class QtPrinterTableView; // ### FIXME: should not be needed friend class QtTableController; void setModel(QtTableModelInterface *model); void setSelectionManager(QtTableSelectionManager *selectionManager); diff --git a/src/qprintertableview.cpp b/src/qprintertableview.cpp new file mode 100644 index 0000000..5329183 --- /dev/null +++ b/src/qprintertableview.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Itemviews NG project on Trolltech Labs. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 or 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "qprintertableview.h" +#include "qprintertableview_p.h" + +#ifndef QT_NO_PRINTER + +#include "qgraphicstableview.h" +#include "qtablemodelinterface.h" + +//#include <qstyleoption.h> +#include <qgraphicsscene.h> +#include <qpainter.h> +#include <qtextdocument.h> +#include <qabstracttextdocumentlayout.h> +#include <qdebug.h> + +// #define DEBUG_TABLES + +QtPrinterTableViewPrivate::QtPrinterTableViewPrivate(QPrinter *p) + : q_ptr(0), + ownsPrinter(p == 0), + printer(ownsPrinter ? new QPrinter : p), + model(0), + orientation(Qt::Vertical), + header(0), + footer(0) +{ + headerFooterSpacing = 5; // in mm +} + +QtPrinterTableViewPrivate::~QtPrinterTableViewPrivate() +{ + delete header; + delete footer; + if (ownsPrinter) + delete printer; +} + +qreal QtPrinterTableViewPrivate::printHeader(QPainter &painter) +{ + if (header == 0) + return 0; + header->drawContents(&painter); + return header->size().height() + headerFooterSpacingInPixels(); +} + +qreal QtPrinterTableViewPrivate::printFooter(QPainter &painter) +{ + if (footer == 0) + return 0; + qreal pageHeight = printer->pageRect().height(); + const qreal footerSize = footer->size().height(); + painter.translate(0, pageHeight - footerSize); + footer->drawContents(&painter); + painter.translate(0, - (pageHeight - footerSize)); + return footerSize + headerFooterSpacingInPixels(); +} + +QTextDocument *QtPrinterTableViewPrivate::getOrCreateHeader() const +{ + if (header == 0) { + header = new QTextDocument(); + header->setUndoRedoEnabled(false); + header->setDocumentMargin(0); + } + return header; +} + +QTextDocument *QtPrinterTableViewPrivate::getOrCreateFooter() const +{ + if (footer == 0) { + footer = new QTextDocument(); + footer->setUndoRedoEnabled(false); + footer->setDocumentMargin(0); + } + return footer; +} + +/*! + \class QtPrinterTableView + \brief QtPrinterTableView allows you to print a table model. +*/ + +QtPrinterTableView::QtPrinterTableView(QtTableModelInterface *model, QtGraphicsHeader *verticalHeader, QtGraphicsHeader *horizontalHeader) + : d_ptr(new QtPrinterTableViewPrivate(0)) +{ + Q_ASSERT(model); + d_ptr->q_ptr = this; + d_ptr->model = model; + d_ptr->horizontalHeader = horizontalHeader; + d_ptr->verticalHeader = verticalHeader; +} + +QtPrinterTableView::QtPrinterTableView(QPrinter *printer, QtTableModelInterface *model, QtGraphicsHeader *verticalHeader, QtGraphicsHeader *horizontalHeader) + : d_ptr(new QtPrinterTableViewPrivate(printer)) +{ + Q_ASSERT(model); + d_ptr->q_ptr = this; + d_ptr->model = model; + d_ptr->horizontalHeader = horizontalHeader; + d_ptr->verticalHeader = verticalHeader; +} + +QtPrinterTableView::~QtPrinterTableView() +{ + delete d_ptr; +} + +QPrinter *QtPrinterTableView::printer() +{ + Q_D(QtPrinterTableView); + return d->printer; +} + +void QtPrinterTableView::setOrientation(Qt::Orientation orientation) +{ + Q_D(QtPrinterTableView); + d->orientation = orientation; +} + +Qt::Orientation QtPrinterTableView::orientation() const +{ + Q_D(const QtPrinterTableView); + return d->orientation; +} + +QTextDocument *QtPrinterTableView::headerDocument() +{ + Q_D(QtPrinterTableView); + return d->getOrCreateHeader(); +} + +QTextDocument *QtPrinterTableView::footerDocument() +{ + Q_D(QtPrinterTableView); + return d->getOrCreateFooter(); +} + +void QtPrinterTableView::setHeaderText(const QString &header) +{ + Q_D(QtPrinterTableView); + d->getOrCreateHeader()->setPlainText(header); +} + +void QtPrinterTableView::setFooterText(const QString &footer) +{ + Q_D(QtPrinterTableView); + d->getOrCreateFooter()->setPlainText(footer); +} + +QString QtPrinterTableView::headerText() const +{ + Q_D(const QtPrinterTableView); + return d->getOrCreateHeader()->toPlainText(); +} + +QString QtPrinterTableView::footerText() const +{ + Q_D(const QtPrinterTableView); + if (d->footer == 0) + return QString(); + return d->footer->toPlainText(); +} + +extern int qt_defaultDpiY(); +extern int qt_defaultDpiX(); + +bool QtPrinterTableView::print() +{ + Q_D(QtPrinterTableView); + if (! d->printer->isValid()) { + qWarning() << "QtPrinterTableView::print: printer not valid, please setup the printer before calling print"; + return false; + } + + // next use a view just for the filling of the options... + QGraphicsScene scene; + QtGraphicsTableView view; + scene.addItem(&view); + view.setModel(d->model); + view.setHorizontalHeader(d->horizontalHeader); + view.setVerticalHeader(d->verticalHeader); + + QPainter painter; + if (!painter.begin(d->printer)) { + qWarning() << "QtPrinterTableView::print: printer fails to begin(), sorry can't print"; + return false; + } + + // re-layout the header footer to the current page size. + if (d->header) { + d->header->documentLayout()->setPaintDevice(d->printer); + d->header->setPageSize(d->printer->pageRect().size()); + } + if (d->footer) { + d->footer->documentLayout()->setPaintDevice(d->printer); + d->footer->setPageSize(d->printer->pageRect().size()); + } + + const qreal headerSize = d->printHeader(painter); + const qreal footerSize = d->printFooter(painter); + const bool vertical = d->orientation == Qt::Vertical; + const qreal scaleX = d->printer->logicalDpiX() / (qreal) qt_defaultDpiX(); + const qreal scaleY = d->printer->logicalDpiY() / (qreal) qt_defaultDpiY(); + painter.scale(scaleX, scaleY); + + const QRect rect = d->printer->pageRect(); + const QSizeF visibleSize(rect.width() / scaleX, rect.height() / scaleY); + + view.setGeometry(0, 0, visibleSize.width(), visibleSize.height()); + view.setHorizontalOffset(0); + + int row = 0; + int column; + bool first = true; + qreal offsetInColumn = 0; // for those columns too wide and thus split over more than one page + while (row < d->model->rowCount()) { + column = 0; + view.setFirstRow(row); + qreal height = visibleSize.height(); + while (true) { + const qreal rowHeight = view.rowHeight(row); + if (height - rowHeight < 0) + break; + if (row >= d->model->rowCount()) + break; + ++row; + height -= rowHeight; + } + while (column < d->model->columnCount()) { + if (!first) + d->printer->newPage(); + first = false; + view.setFirstColumn(column); + view.setHorizontalOffset(offsetInColumn); + + qreal width = visibleSize.width(); + while (true) { + const qreal columnWidth = view.columnWidth(column); + if (width == visibleSize.width() && columnWidth - offsetInColumn > visibleSize.width()) { + // the column doesn't fit on a page. Lets split it. + offsetInColumn += visibleSize.width(); + break; + } else if (offsetInColumn > 0) { // we still have a part of a split column to print! + width -= columnWidth - offsetInColumn; + offsetInColumn = 0; + ++column; + continue; + } + + if (width - columnWidth + offsetInColumn < 0) { + break; + } + if (column >= d->model->columnCount()) + break; + ++column; + width -= columnWidth; + } +#ifdef DEBUG_TABLES + painter.setPen(QPen(QColor(Qt::green))); + painter.drawRect(QRectF(0, 0, visibleSize.width() - width, visibleSize.height() - height)); +#endif + view.doLayout(); + // find and paint children which are the cells + QList<QGraphicsItem*> items = scene.items(view.rect()); + QList<QGraphicsItem*>::Iterator iter = items.begin(); + for (;iter != items.end(); ++iter) { + QGraphicsItem *parent = *iter; + while (parent != &view && parent != 0) + parent = parent->parentItem(); + if (parent == 0) + continue; + if (!(*iter)->isVisible()) + continue; + painter.save(); + painter.translate((*iter)->mapToItem(&view, QPointF())); +#ifdef DEBUG_TABLES + QGraphicsWidget *w = dynamic_cast<QGraphicsWidget*>(*iter); + if (w) { + painter.save(); + painter.setPen(QPen(QColor(Qt::red))); + painter.drawRect(QRectF(QPointF(), w->size())); + painter.restore(); + } +#endif + (*iter)->paint(&painter, 0); + painter.restore(); + } + } + } + +/* + QSizeF constraint = d->printer->pageRect().size(); + // cache the space we have for actual table items. + const qreal contentSize = vertical ? constraint.height() - headerSize - footerSize : constraint.width(); + + // a constraint is -1 in the direction we allow items to grow in. + if (vertical) { + constraint.setHeight(-1); + } else { + constraint.setWidth(-1); + // in this direction headers/footers eat our precious space + constraint.setHeight(constraint.height() - headerSize - - footerSize); + } + + qreal progression = vertical ? headerSize : 0; // init + const int max = d->model->count(); + for (int index = 0; index < max; ++index) { + view.initStyleOption(&widgetOptions, index); + + QSizeF itemSize = tableViewItem->sizeHint(index, &widgetOptions, Qt::PreferredSize, constraint); + tableViewItem->setIndex(index); + QRectF geometry(QPointF(), itemSize); + if (vertical) + geometry.setWidth(constraint.width() / scaleX); + else + geometry.setHeight(constraint.height() / scaleY - headerSize - footerSize); + tableViewItem->setGeometry(geometry); + geometry = tableViewItem->geometry();// the tableViewItem can be stubborn + graphicsViewOptions.rect = geometry.toRect(); + if ((vertical && progression - headerSize + geometry.height() > contentSize) + || (!vertical && progression + geometry.width()> contentSize)) { + if (! d->printer->newPage()) { + qWarning() << "QtPrinterTableView::print: Failed to start a new page, aborting printing"; + return false; + } + progression = vertical ? headerSize : 0; // reset + d->printHeader(painter); + d->printFooter(painter); + } + + painter.save(); + painter.translate(vertical ? 0 : progression, + vertical ? progression : headerSize); + painter.scale(scaleX, scaleY); + tableViewItem->paint(&painter, &graphicsViewOptions); + painter.restore(); + progression += vertical ? geometry.height() * scaleY: geometry.width() * scaleX; + } +*/ + return true; +} + +#endif diff --git a/src/qprintertableview.h b/src/qprintertableview.h new file mode 100644 index 0000000..be08ca6 --- /dev/null +++ b/src/qprintertableview.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Itemviews NG project on Trolltech Labs. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 or 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ +#ifndef QTPRINTERTABLEVIEW_H +#define QTPRINTERLTABLEIEW_H + +#include <QtGui/qprinter.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +//QT_MODULE(Gui) + +class QtPrinterTableViewPrivate; +class QtTableModelInterface; +class QtGraphicsHeader; +class QTextDocument; + +class Q_ITEMVIEWSNG_EXPORT QtPrinterTableView +{ +public: + explicit QtPrinterTableView(QPrinter *printer, QtTableModelInterface *model, QtGraphicsHeader *verticalHeader = 0, QtGraphicsHeader *horizontalHeader = 0); + explicit QtPrinterTableView(QtTableModelInterface *model, QtGraphicsHeader *verticalHeader = 0, QtGraphicsHeader *horizontalHeader = 0); + ~QtPrinterTableView(); + + QPrinter *printer(); + bool print(); + + void setOrientation(Qt::Orientation orientation); + Qt::Orientation orientation() const; + + QTextDocument *headerDocument(); + QTextDocument *footerDocument(); + + void setHeaderText(const QString &header); + void setFooterText(const QString &footer); + QString headerText() const; + QString footerText() const; + + // TODO add the setter of the creator object, add static print object + +protected: + QtPrinterTableViewPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QtPrinterTableView) + Q_DISABLE_COPY(QtPrinterTableView) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //QTPRINTERTABLEVIEW_H diff --git a/src/qprintertableview_p.h b/src/qprintertableview_p.h new file mode 100644 index 0000000..f2927c2 --- /dev/null +++ b/src/qprintertableview_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Itemviews NG project on Trolltech Labs. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 or 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef QTPRINTERTABLEVIEW_P_H +#define QTPRINTERTABLEVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PRINTER +class QTextDocument; + +class QtPrinterTableViewPrivate +{ + Q_DECLARE_PUBLIC(QtPrinterTableView) +public: + QtPrinterTableViewPrivate(QPrinter *printer); + ~QtPrinterTableViewPrivate(); + + QtPrinterTableView *q_ptr; + + bool ownsPrinter; + QPrinter * const printer; + QtTableModelInterface *model; + QtGraphicsHeader *horizontalHeader; + QtGraphicsHeader *verticalHeader; + + Qt::Orientation orientation; + mutable QTextDocument *header; + mutable QTextDocument *footer; + + qreal headerFooterSpacing; // in mm + + /// print a header and return the height we used + qreal printHeader(QPainter &painter); + qreal printFooter(QPainter &painter); + QTextDocument *getOrCreateHeader() const; + QTextDocument *getOrCreateFooter() const; + inline qreal headerFooterSpacingInPixels() { + return headerFooterSpacing * (printer->resolution() / 25.4); + } +}; + +#endif +QT_END_NAMESPACE + +#endif//QTPRINTERTABLEVIEW_P_H diff --git a/src/src.pro b/src/src.pro index 3b2957c..bc0f8f5 100644 --- a/src/src.pro +++ b/src/src.pro @@ -19,6 +19,8 @@ HEADERS += qgraphicsscrollbar.h \ qlistwidgetng_p.h \ qprinterlistview.h \ qprinterlistview_p.h \ + qprintertableview.h \ + qprintertableview_p.h \ qsectionspans_p.h \ qtablecontroller.h \ qtablecontroller_p.h \ @@ -60,6 +62,7 @@ SOURCES += qgraphicsscrollbar.cpp \ qlistselectionmanager.cpp \ qlistwidgetng.cpp \ qprinterlistview.cpp \ + qprintertableview.cpp \ qtablecontroller.cpp \ qgraphicstableview.cpp \ qtabledefaultmodel.cpp \ |