summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--display.h7
-rw-r--r--qt-ui/printlayout.cpp462
-rw-r--r--qt-ui/printlayout.h49
4 files changed, 1 insertions, 518 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1901ac599..3ada22a35 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -324,7 +324,6 @@ set(SUBSURFACE_INTERFACE
qt-ui/notificationwidget.cpp
qt-ui/preferences.cpp
qt-ui/printdialog.cpp
- qt-ui/printlayout.cpp
qt-ui/printoptions.cpp
qt-ui/simplewidgets.cpp
qt-ui/starwidget.cpp
diff --git a/display.h b/display.h
index 72b5c99fc..53131e043 100644
--- a/display.h
+++ b/display.h
@@ -37,18 +37,13 @@ extern struct divecomputer *select_dc(struct dive *);
struct print_options {
enum print_type {
- PRETTY,
- TABLE,
- TWOPERPAGE,
- ONEPERPAGE,
DIVELIST,
+ TABLE,
STATISTICS
} type;
bool print_selected;
bool color_selected;
- bool notes_up;
bool landscape;
- int margins[4]; // left, top, right, bottom
};
extern unsigned int dc_number;
diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp
deleted file mode 100644
index 87f5f7c30..000000000
--- a/qt-ui/printlayout.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-#include <QtCore/qmath.h>
-#include <QDesktopWidget>
-#include <QPicture>
-#include <QMessageBox>
-#include <QPointer>
-#include <QTableView>
-
-#include "mainwindow.h"
-#include "printdialog.h"
-#include "printlayout.h"
-#include "modeldelegates.h"
-#include "models.h"
-#include "profile/profilewidget2.h"
-#include "divetripmodel.h"
-#include "tableprintmodel.h"
-#include "profileprintmodel.h"
-
-PrintLayout::PrintLayout(PrintDialog *dialogPtr, QPrinter *printerPtr, struct print_options *optionsPtr)
-{
- dialog = dialogPtr;
- printer = printerPtr;
- printOptions = optionsPtr;
-
- // table print settings
- tablePrintHeadingBackground = 0xffeeeeee;
- tablePrintColumnNames.append(tr("Dive#"));
- tablePrintColumnNames.append(tr("Date"));
- tablePrintColumnNames.append(tr("Depth"));
- tablePrintColumnNames.append(tr("Duration"));
- tablePrintColumnNames.append(tr("Master"));
- tablePrintColumnNames.append(tr("Buddy"));
- tablePrintColumnNames.append(tr("Location"));
- tablePrintColumnWidths.append(7);
- tablePrintColumnWidths.append(14);
- tablePrintColumnWidths.append(8);
- tablePrintColumnWidths.append(8);
- tablePrintColumnWidths.append(15);
- tablePrintColumnWidths.append(15);
- tablePrintColumnWidths.append(33);
- // profile print settings
- const int dw = 20; // base percentage
- profilePrintColumnWidths.append(dw);
- profilePrintColumnWidths.append(dw);
- profilePrintColumnWidths.append(dw + 8);
- profilePrintColumnWidths.append(dw - 4);
- profilePrintColumnWidths.append(dw - 4); // fit to 100%
- const int sr = 12; // smallest row height in pixels
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr + 4);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
- profilePrintRowHeights.append(sr);
-}
-
-void PrintLayout::print()
-{
- // we call setup each time to check if the printer properties have changed
- setup();
- if (pageW == 0 || pageH == 0) {
- QMessageBox msgBox;
- msgBox.setIcon(QMessageBox::Critical);
- msgBox.setText(tr("Subsurface cannot find a usable printer on this system!"));
- msgBox.setWindowIcon(QIcon(":subsurface-icon"));
- msgBox.exec();
- return;
- }
- switch (printOptions->type) {
- case print_options::PRETTY:
- printProfileDives(3, 2);
- break;
- case print_options::ONEPERPAGE:
- printProfileDives(1, 1);
- break;
- case print_options::TWOPERPAGE:
- printProfileDives(2, 1);
- break;
- case print_options::TABLE:
- printTable();
- break;
- }
-}
-
-void PrintLayout::setup()
-{
- QDesktopWidget *desktop = QApplication::desktop();
- screenDpiX = desktop->physicalDpiX();
- screenDpiY = desktop->physicalDpiY();
-
- printerDpi = printer->resolution();
- pageRect = printer->pageRect();
-
- // a printer page in pixels
- pageW = pageRect.width();
- pageH = pageRect.height();
-}
-
-// go trought the dive table and find how many dives we are a going to print
-// TODO: C function: 'count_selected_dives' or something
-int PrintLayout::estimateTotalDives() const
-{
- int total = 0, i = 0;
- struct dive *dive;
- for_each_dive (i, dive) {
- if (!dive->selected && printOptions->print_selected)
- continue;
- total++;
- }
- return total;
-}
-
-/* the used formula here is:
- * s = (S - (n - 1) * p) / n
- * where:
- * s is the length of a single element (unknown)
- * S is the total available length
- * n is the number of elements to fit
- * p is the padding between elements
- */
-#define ESTIMATE_DIVE_DIM(S, n, p) \
- ((S) - ((n) - 1) * (p)) / (n);
-
-void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn)
-{
- int i, row = 0, col = 0, printed = 0, total = estimateTotalDives();
- int animationOriginal = prefs.animation_speed;
-
- struct dive *dive;
- if (!total)
- return;
-
- // disable animations on the profile:
- prefs.animation_speed = 0;
-
- // setup a painter
- QPainter painter;
- painter.begin(printer);
- painter.setRenderHint(QPainter::Antialiasing);
- painter.setRenderHint(QPainter::SmoothPixmapTransform);
-
- // setup the profile widget
- QPointer<ProfileWidget2> profile = MainWindow::instance()->graphics();
- const int profileFrameStyle = profile->frameStyle();
- profile->setFrameStyle(QFrame::NoFrame);
- profile->setPrintMode(true, !printOptions->color_selected);
- profile->setFontPrintScale(divesPerRow * divesPerColumn > 3 ? 0.6 : 1.0);
- QSize originalSize = profile->size();
- // swap rows/col for landscape
- if (printer->orientation() == QPrinter::Landscape) {
- int swap = divesPerColumn;
- divesPerColumn = divesPerRow;
- divesPerRow = swap;
- }
-
- // padding in pixels between two dives. no padding if only one dive per page.
- const int padDef = 20;
- const int padW = (divesPerColumn < 2) ? 0 : padDef;
- const int padH = (divesPerRow < 2) ? 0 : padDef;
- // estimate dimensions for a single dive
- const int scaledW = ESTIMATE_DIVE_DIM(pageW, divesPerColumn, padW);
- const int scaledH = ESTIMATE_DIVE_DIM(pageH, divesPerRow, padH);
- // padding in pixels between profile and table
- const int padPT = 5;
- // create a model and table
- ProfilePrintModel model;
- model.setFontsize(7); // if this is changed we also need to change 'const int sr' in the constructor
- // if there is only one dive per page row we pass fitNotesToHeight to be almost half the page height
- QPointer<QTableView> table(createProfileTable(&model, scaledW, (divesPerRow == 1) ? scaledH * 0.45 : 0.0));
- // profilePrintTableMaxH updates after the table is created
- const int tableH = profilePrintTableMaxH;
- // resize the profile widget
- profile->resize(scaledW, scaledH - tableH - padPT);
- // offset table or profile on top
- int yOffsetProfile = 0, yOffsetTable = 0;
- if (printOptions->notes_up)
- yOffsetProfile = tableH + padPT;
- else
- yOffsetTable = scaledH - tableH;
-
- // plot the dives at specific rows and columns on the page
- for_each_dive (i, dive) {
- if (!dive->selected && printOptions->print_selected)
- continue;
- if (col == divesPerColumn) {
- col = 0;
- row++;
- if (row == divesPerRow) {
- row = 0;
- printer->newPage();
- }
- }
- // draw a profile
- QTransform origTransform = painter.transform();
- painter.translate((scaledW + padW) * col, (scaledH + padH) * row + yOffsetProfile);
- profile->plotDive(dive, true); // make sure the profile is actually redrawn
-#ifdef Q_OS_LINUX // on Linux there is a vector line bug (big lines in PDF), which forces us to render to QImage
- QImage image(scaledW, scaledH - tableH - padPT, QImage::Format_ARGB32);
- QPainter imgPainter(&image);
- imgPainter.setRenderHint(QPainter::Antialiasing);
- imgPainter.setRenderHint(QPainter::SmoothPixmapTransform);
- profile->render(&imgPainter, QRect(0, 0, scaledW, scaledH - tableH - padPT));
- imgPainter.end();
- painter.drawImage(image.rect(),image);
-#else // for other OS we can try rendering the profile as vector
- profile->render(&painter, QRect(0, 0, scaledW, scaledH - tableH - padPT));
-#endif
- painter.setTransform(origTransform);
-
- // draw a table
- QPicture pic;
- QPainter picPainter;
- painter.translate((scaledW + padW) * col, (scaledH + padH) * row + yOffsetTable);
- model.setDive(dive);
- picPainter.begin(&pic);
- table->render(&picPainter);
- picPainter.end();
- painter.drawPicture(QPoint(0,0), pic);
- painter.setTransform(origTransform);
- col++;
- printed++;
- emit signalProgress((printed * 100) / total);
- }
- // cleanup
- painter.end();
- profile->setFrameStyle(profileFrameStyle);
- profile->setPrintMode(false);
- profile->resize(originalSize);
- // we need to force a redraw of the profile so it switches back from print mode
- profile->plotDive(0, true);
- // re-enable animations
- prefs.animation_speed = animationOriginal;
-}
-
-/* we create a table that has a fixed height, but can stretch to fit certain width */
-QTableView *PrintLayout::createProfileTable(ProfilePrintModel *model, const int tableW, const qreal fitNotesToHeight)
-{
- // setup a new table
- QTableView *table = new QTableView();
- QHeaderView *vHeader = table->verticalHeader();
- QHeaderView *hHeader = table->horizontalHeader();
- table->setAttribute(Qt::WA_DontShowOnScreen);
- table->setSelectionMode(QAbstractItemView::NoSelection);
- table->setFocusPolicy(Qt::NoFocus);
- table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- hHeader->setVisible(false);
- vHeader->setVisible(false);
- hHeader->setSectionResizeMode(QHeaderView::Fixed);
- vHeader->setSectionResizeMode(QHeaderView::Fixed);
- // set the model
- table->setModel(model);
-
- /* setup cell span for the table using QTableView::setSpan().
- * changes made here reflect on ProfilePrintModel::data(). */
- const int cols = model->columnCount();
- const int rows = model->rowCount();
- // info on top
- table->setSpan(0, 0, 1, 3);
- table->setSpan(1, 0, 1, 3);
- table->setSpan(0, 3, 1, 2);
- table->setSpan(1, 3, 1, 2);
- // gas used
- table->setSpan(2, 0, 1, 2);
- table->setSpan(3, 0, 1, 2);
- // notes
- table->setSpan(6, 0, 1, 5);
- table->setSpan(7, 0, 5, 5);
- /* resize row heights to the 'profilePrintRowHeights' indexes.
- * profilePrintTableMaxH will then hold the table height.
- * what fitNotesToHeight does it to expand the notes section to fit a special height */
- int i;
- profilePrintTableMaxH = 0;
- for (i = 0; i < rows; i++) {
- int h = (i == rows - 1 && fitNotesToHeight != 0.0) ? fitNotesToHeight : profilePrintRowHeights.at(i);
- profilePrintTableMaxH += h;
- vHeader->resizeSection(i, h);
- }
-
- // resize columns. columns widths are percentages from the table width.
- int accW = 0;
- for (i = 0; i < cols; i++) {
- int pw = qCeil((qreal)(profilePrintColumnWidths.at(i) * tableW) / 100.0);
- accW += pw;
- if (i == cols - 1 && accW > tableW) /* adjust last column */
- pw -= accW - tableW;
- hHeader->resizeSection(i, pw);
- }
- // resize
- table->resize(tableW, profilePrintTableMaxH);
- // hide the grid and set a stylesheet
- table->setItemDelegate(new ProfilePrintDelegate(table));
- table->setItemDelegateForRow(7, new HTMLDelegate(table));
-
- table->setShowGrid(false);
- table->setStyleSheet(
- "QTableView { border: none }"
- "QTableView::item { border: 0px; padding-left: 2px; padding-right: 2px; }");
- // return
- return table;
-}
-
-void PrintLayout::printTable()
-{
- struct dive *dive;
- int done = 0; // percents done
- int i, row = 0, progress, total = estimateTotalDives();
- if (!total)
- return;
-
- // create and setup a table
- QTableView table;
- table.setAttribute(Qt::WA_DontShowOnScreen);
- table.setSelectionMode(QAbstractItemView::NoSelection);
- table.setFocusPolicy(Qt::NoFocus);
- table.horizontalHeader()->setVisible(false);
- table.verticalHeader()->setVisible(false);
- table.horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
- table.verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
- table.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- table.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- // fit table to one page initially
- table.resize(pageW, pageH);
-
- // don't show border
- table.setStyleSheet(
- "QTableView { border: none }");
-
- // create and fill a table model
- TablePrintModel model;
- addTablePrintHeadingRow(&model, row); // add one heading row
- row++;
- progress = 0;
- for_each_dive (i, dive) {
- if (!dive->selected && printOptions->print_selected)
- continue;
- addTablePrintDataRow(&model, row, dive);
- row++;
- progress++;
- emit signalProgress((progress * 10) / total);
- }
- done = 10;
- table.setModel(&model); // set model to table
- // resize columns to percentages from page width
- int accW = 0;
- int cols = model.columns;
- int tableW = table.width();
- for (i = 0; i < model.columns; i++) {
- int pw = qCeil((qreal)(tablePrintColumnWidths.at(i) * table.width()) / 100.0);
- accW += pw;
- if (i == cols - 1 && accW > tableW) /* adjust last column */
- pw -= accW - tableW;
- table.horizontalHeader()->resizeSection(i, pw);
- }
- // reset the model at this point
- model.callReset();
-
- // a list of vertical offsets where pages begin and some helpers
- QList<unsigned int> pageIndexes;
- pageIndexes.append(0);
-
- /* the algorithm bellow processes the table rows in multiple passes,
- * compensating for loss of space due to moving rows on a new page instead
- * of truncating them.
- * there is a 'passes' array defining how much percents of the total
- * progress each will take. given, the first and last stage of this function
- * use 10% each, then the sum of passes[] here should be 80%.
- * two should be enough! */
- const int passes[] = { 70, 10 };
- int tableHeight = 0, lastAccIndex = 0, rowH, accH, headings, headingRowHeightD2, headingRowHeight;
- bool newHeading = false;
-
- for (unsigned int pass = 0; pass < sizeof(passes) / sizeof(passes[0]); pass++) {
- progress = headings = accH = 0;
- total = model.rows - lastAccIndex;
- for (i = lastAccIndex; i < model.rows; i++) {
- rowH = table.rowHeight(i);
- if (i == 0) { // first row is always a heading. it's height is constant.
- headingRowHeight = rowH;
- headingRowHeightD2 = rowH / 2;
- }
- if (rowH > pageH - headingRowHeight) // skip huge rows. we don't support row spanning on multiple pages.
- continue;
- accH += rowH;
- if (newHeading) {
- headings += rowH;
- newHeading = false;
- }
- if (accH > pageH) {
- lastAccIndex = i;
- pageIndexes.append(pageIndexes.last() + (accH - rowH));
- addTablePrintHeadingRow(&model, i);
- newHeading = true;
- accH = 0;
- i--;
- }
- tableHeight += table.rowHeight(i);
- progress++;
- emit signalProgress(done + (progress * passes[pass]) / total);
- }
- done += passes[pass];
- }
- done = 90;
- pageIndexes.append(pageIndexes.last() + accH + headings);
- table.resize(pageW, tableHeight);
-
- /* attach a painter and render pages by using pageIndexes
- * there is a weird QPicture dependency here; we need to offset a page
- * by headingRowHeightD2, which is half the heading height. the same doesn't
- * make sense if we are rendering the table widget directly to the printer-painter. */
- QPainter painter(printer);
- painter.setRenderHint(QPainter::Antialiasing);
- painter.setRenderHint(QPainter::SmoothPixmapTransform);
- total = pageIndexes.size() - 1;
- progress = 0;
- for (i = 0; i < total; i++) {
- if (i > 0)
- printer->newPage();
-
- QRegion region(0, pageIndexes.at(i) + headingRowHeightD2 - 1,
- table.width(),
- pageIndexes.at(i + 1) - (pageIndexes.at(i) + headingRowHeightD2) + 1);
- // vectorize the table first by using QPicture
- QPicture pic;
- QPainter picPainter;
- picPainter.begin(&pic);
- table.render(&picPainter, QPoint(0, 0), region);
- picPainter.end();
- painter.drawPicture(QPoint(0, headingRowHeightD2), pic);
-
- progress++;
- emit signalProgress(done + (progress * 10) / total);
- }
-}
-
-void PrintLayout::addTablePrintDataRow(TablePrintModel *model, int row, struct dive *dive) const
-{
- struct DiveItem di;
- di.diveId = dive->id;
- model->insertRow();
- model->setData(model->index(row, 0), QString::number(dive->number), Qt::DisplayRole);
- model->setData(model->index(row, 1), di.displayDate(), Qt::DisplayRole);
- model->setData(model->index(row, 2), di.displayDepthWithUnit(), Qt::DisplayRole);
- model->setData(model->index(row, 3), di.displayDuration(), Qt::DisplayRole);
- model->setData(model->index(row, 4), dive->divemaster, Qt::DisplayRole);
- model->setData(model->index(row, 5), dive->buddy, Qt::DisplayRole);
- model->setData(model->index(row, 6), get_dive_location(dive), Qt::DisplayRole);
-}
-
-void PrintLayout::addTablePrintHeadingRow(TablePrintModel *model, int row) const
-{
- model->insertRow(row);
- for (int i = 0; i < model->columns; i++) {
- model->setData(model->index(row, i), tablePrintColumnNames.at(i), Qt::DisplayRole);
- model->setData(model->index(row, i), tablePrintHeadingBackground, Qt::BackgroundRole);
- }
-}
diff --git a/qt-ui/printlayout.h b/qt-ui/printlayout.h
deleted file mode 100644
index d8c730a50..000000000
--- a/qt-ui/printlayout.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef PRINTLAYOUT_H
-#define PRINTLAYOUT_H
-
-#include <QObject>
-#include <QList>
-#include <QVector>
-#include <QRect>
-
-class QPrinter;
-class QTableView;
-class PrintDialog;
-class TablePrintModel;
-class ProfilePrintModel;
-struct dive;
-
-class PrintLayout : public QObject {
- Q_OBJECT
-
-public:
- PrintLayout(PrintDialog *, QPrinter *, struct print_options *);
- void print();
-
-private:
- PrintDialog *dialog;
- QPrinter *printer;
- struct print_options *printOptions;
-
- int screenDpiX, screenDpiY, printerDpi, pageW, pageH;
- QRect pageRect;
-
- QVector<QString> tablePrintColumnNames;
- unsigned int tablePrintHeadingBackground;
- QList<unsigned int> tablePrintColumnWidths;
- unsigned int profilePrintTableMaxH;
- QList<unsigned int> profilePrintColumnWidths, profilePrintRowHeights;
-
- void setup();
- int estimateTotalDives() const;
- void printProfileDives(int divesPerRow, int divesPerColumn);
- QTableView *createProfileTable(ProfilePrintModel *model, const int tableW, const qreal fitNotesToHeight = 0.0);
- void printTable();
- void addTablePrintDataRow(TablePrintModel *model, int row, struct dive *dive) const;
- void addTablePrintHeadingRow(TablePrintModel *model, int row) const;
-
-signals:
- void signalProgress(int);
-};
-
-#endif // PRINTLAYOUT_H