1 #ifndef PDFEXPORT_H 2 #define PDFEXPORT_H 3 4 #include "pdfexport_global.h" 5 #include "plugins/genericexportplugin.h" 6 #include "config_builder.h" 7 #include <QPdfWriter> 8 #include <QFont> 9 #include <QColor> 10 11 class QPagedPaintDevice; 12 class QPainter; 13 class QTextOption; 14 class QFont; 15 16 namespace Cfg 17 { 18 PDFEXPORTSHARED_EXPORT QFont getPdfExportDefaultFont(); 19 PDFEXPORTSHARED_EXPORT QStringList getPdfPageSizes(); 20 } 21 22 CFG_CATEGORIES(PdfExportConfig, 23 CFG_CATEGORY(PdfExport, 24 CFG_ENTRY(QString, PageSize, "A4") 25 CFG_ENTRY(QStringList, PageSizes, Cfg::getPdfPageSizes()) 26 CFG_ENTRY(int, Padding, 1) 27 CFG_ENTRY(bool, PrintRowNum, true) 28 CFG_ENTRY(bool, PrintPageNumbers, true) 29 CFG_ENTRY(int, TopMargin, 20) 30 CFG_ENTRY(int, RightMargin, 20) 31 CFG_ENTRY(int, BottomMargin, 20) 32 CFG_ENTRY(int, LeftMargin, 20) 33 CFG_ENTRY(int, MaxCellBytes, 100) 34 CFG_ENTRY(QFont, Font, Cfg::getPdfExportDefaultFont()) 35 CFG_ENTRY(int, FontSize, 10) 36 CFG_ENTRY(QColor, HeaderBgColor, QColor(Qt::lightGray)) 37 CFG_ENTRY(QColor, NullValueColor, QColor(Qt::gray)) 38 ) 39 ) 40 41 class PDFEXPORTSHARED_EXPORT PdfExport : public GenericExportPlugin 42 { 43 Q_OBJECT 44 SQLITESTUDIO_PLUGIN("pdfexport.json") 45 46 public: 47 QString getFormatName() const; 48 ExportManager::StandardConfigFlags standardOptionsToEnable() const; 49 ExportManager::ExportProviderFlags getProviderFlags() const; 50 void validateOptions(); 51 CfgMain* getConfig(); 52 QString getExportConfigFormName() const; 53 QString defaultFileExtension() const; 54 bool beforeExportQueryResults(const QString& query, QList<QueryExecutor::ResultColumnPtr>& columns, 55 const QHash<ExportManager::ExportProviderFlag,QVariant> providedData); 56 bool exportQueryResultsRow(SqlResultsRowPtr row); 57 bool exportTable(const QString& database, const QString& table, const QStringList& columnNames, const QString& ddl, SqliteCreateTablePtr createTable, 58 const QHash<ExportManager::ExportProviderFlag,QVariant> providedData); 59 bool exportVirtualTable(const QString& database, const QString& table, const QStringList& columnNames, const QString& ddl, SqliteCreateVirtualTablePtr createTable, 60 const QHash<ExportManager::ExportProviderFlag,QVariant> providedData); 61 bool afterExport(); 62 bool afterExportTable(); 63 bool afterExportQueryResults(); 64 bool exportTableRow(SqlResultsRowPtr data); 65 bool beforeExportDatabase(const QString& database); 66 bool exportIndex(const QString& database, const QString& name, const QString& ddl, SqliteCreateIndexPtr createIndex); 67 bool exportTrigger(const QString& database, const QString& name, const QString& ddl, SqliteCreateTriggerPtr createTrigger); 68 bool exportView(const QString& database, const QString& name, const QString& ddl, SqliteCreateViewPtr view); 69 void cleanupAfterExport(); 70 bool isBinaryData() const; 71 bool init(); 72 void deinit(); 73 74 protected: 75 virtual QPagedPaintDevice* createPaintDevice(const QString& documentTitle, bool& takeOwnership); 76 77 int lineWidth = 15; 78 79 private: 80 struct DataCell 81 { 82 QString contents; 83 Qt::Alignment alignment = Qt::AlignLeft; 84 bool isNull = false; 85 bool isRowNum = false; 86 }; 87 88 struct DataRow 89 { 90 enum class Type 91 { 92 NORMAL, 93 TOP_HEADER, 94 COLUMNS_HEADER 95 }; 96 97 QList<DataCell> cells; 98 int height = 0; 99 Type type = Type::NORMAL; 100 }; 101 102 struct ObjectCell 103 { 104 enum class Type 105 { 106 NORMAL, 107 LIST 108 }; 109 110 QStringList contents; 111 Qt::Alignment alignment = Qt::AlignLeft; 112 bool headerBackground = false; 113 bool bold = false; 114 bool italic = false; 115 Type type = Type::NORMAL; 116 }; 117 118 struct ObjectRow 119 { 120 enum class Type 121 { 122 MULTI, 123 SINGLE 124 }; 125 126 QList<ObjectCell> cells; 127 int height = 0; 128 Type type = Type::SINGLE; 129 bool recalculateColumnWidths = false; 130 }; 131 132 void prepareTableDataExport(const QString& table, const QStringList& columnNames, const QHash<ExportManager::ExportProviderFlag,QVariant> providedData); 133 QList<int> getColumnDataLengths(int columnCount, const QHash<ExportManager::ExportProviderFlag,QVariant> providedData); 134 bool beginDoc(const QString& title); 135 void endDoc(); 136 void setupConfig(); 137 void updateMargins(); 138 void drawDdl(const QString& objName, const QString& ddl); 139 void clearDataHeaders(); 140 void resetDataTable(); 141 void exportDataHeader(const QString& contents); 142 void exportDataColumnsHeader(const QStringList& columns); 143 void exportDataRow(const QList<QVariant>& data); 144 void exportObjectHeader(const QString& contents); 145 void exportObjectColumnsHeader(const QStringList& columns); 146 void exportTableColumnRow(SqliteCreateTable::Column* column); 147 void exportTableConstraintsRow(const QList<SqliteCreateTable::Constraint*>& constrList); 148 void exportObjectRow(const QStringList& values); 149 void exportObjectRow(const QString& values); 150 void checkForDataRender(); 151 void flushObjectPages(); 152 void drawObjectTopLine(int y); 153 void drawObjectCellHeaderBackground(int x1, int y1, int x2, int y2); 154 void drawFooter(); 155 void flushObjectRow(const ObjectRow& row, int y); 156 void flushObjectCell(const ObjectCell& cell, int x, int y, int w, int h); 157 void flushDataPages(bool forceRender = false); 158 void flushDataRowsPage(int columnStart, int columnEndBefore, int rowsToRender); 159 void flushDataRow(const DataRow& row, int& y, int columnStart, int columnEndBefore, int localRowNum); 160 void flushDataCell(const QRect& rect, const DataCell& cell); 161 void flushDataCell(const QRect& rect, const QString& contents, QTextOption* opt); 162 void flushDataHeaderRow(const DataRow& row, int& y, int totalColsWidth, int columnStart, int columnEndBefore); 163 void flushDataHeaderCell(int& x, int y, const DataRow& row, int col, QTextOption* opt); 164 void renderPageNumber(); 165 int getPageNumberHeight(); 166 void newPage(); 167 void calculateDataColumnWidths(const QStringList& columnNames, const QList<int>& columnDataLengths, int columnToExpand = -1); 168 void calculateDataRowHeights(); 169 int calculateRowHeight(int textWidth, const QString& contents); 170 int calculateRowHeight(int maxTextWidth, const QStringList& listContents); 171 int calculateBulletPrefixWidth(); 172 void calculateObjectColumnWidths(int columnToExpand = -1); 173 int correctMaxObjectColumnWidths(int colCount, int columnToExpand); 174 void calculateObjectRowHeights(); 175 int getDataColumnsWidth() const; 176 int getDataColumnsStartX() const; 177 int getContentsLeft() const; 178 int getContentsTop() const; 179 int getContentsRight() const; 180 int getContentsBottom() const; 181 qreal mmToPoints(qreal sizeMM); 182 183 CFG_LOCAL_PERSISTABLE(PdfExportConfig, cfg) 184 QPagedPaintDevice* pagedWriter = nullptr; 185 bool takeDeviceOwnership = true; 186 QPainter* painter = nullptr; 187 QTextOption* textOption = nullptr; 188 QFont stdFont; 189 QFont boldFont; 190 QFont italicFont; 191 int totalRows = 0; 192 QList<ObjectRow> bufferedObjectRows; // object rows (for exporting ddl of all object) 193 QList<DataRow> bufferedDataRows; // data rows 194 int totalHeaderRowsHeight = 0; // total height of all current header rows 195 int currentHeaderMinWidth = 0; // minimum width of the object header, required to extend data columns when hey are slimmer than this 196 QList<int> calculatedObjectColumnWidths; // object column widths calculated basing on header column widths and columns from other object rows 197 QList<int> calculatedDataColumnWidths; // data column widths calculated basing on header column widths and data column widths 198 QList<int> columnsPerPage; // number of columns that will fit on each page 199 QScopedPointer<DataRow> headerRow; // Top level header (object name) 200 QScopedPointer<DataRow> columnsHeaderRow; // columns header for data tables 201 int rowNumColumnWidth = 0; 202 int pageWidth = 0; 203 int pageHeight = 0; 204 int minRowHeight = 0; 205 int rowsToPrebuffer = 0; 206 int currentPage = -1; 207 int rowNum = 0; 208 int lastRowY = 0; 209 qreal pointsPerMm = 1.0; 210 int maxColWidth = 0; 211 int maxRowHeight = 0; 212 int cellDataLimit = 100; 213 214 static QString bulletChar; 215 216 // Configurable fields 217 int padding = 0; 218 bool printRowNum = true; 219 bool printPageNumbers = true; 220 int topMargin = 0; 221 int rightMargin = 0; 222 int leftMargin = 0; 223 int bottomMargin = 0; 224 }; 225 226 #endif // PDFEXPORT_H 227