LCOV - code coverage report
Current view: top level - src/converters - convertertopdf.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 239 265 90.2 %
Date: 2019-05-08 03:46:12 Functions: 10 10 100.0 %

          Line data    Source code
       1             : #include "convertertopdf.hpp"
       2             : 
       3             : #include <QPdfWriter>
       4             : #include <QPainter>
       5             : #include "utils/replacer.hpp"
       6             : #include "convertertoqwidget.hpp"
       7             : 
       8             : namespace qtreports {
       9             :     namespace detail {
      10             : 
      11           9 :         ConverterToPDF::ConverterToPDF(const ReportPtr & report) :
      12             :             m_report(report),
      13             :             m_currentResolution(75),
      14           9 :             m_currentHeight(0) {}
      15             : 
      16             : 
      17           9 :         ConverterToPDF::~ConverterToPDF() {}
      18             : 
      19           6 :         bool    ConverterToPDF::convert(const QString & path)
      20             :         {
      21           6 :             return create(path);
      22             :         }
      23             : 
      24           1 :         void    ConverterToPDF::setDPI(int dpi)
      25             :         {
      26           1 :             m_currentResolution = dpi;
      27           1 :         }
      28             : 
      29           3 :         int     ConverterToPDF::getDPI() const
      30             :         {
      31           3 :             return m_currentResolution;
      32             :         }
      33             : 
      34           6 :         bool    ConverterToPDF::create(const QString & path)
      35             :         {
      36           6 :             if(m_report.isNull()) {
      37           1 :                 m_lastError = "Report is empty";
      38           1 :                 return false;
      39             :             }
      40             : 
      41          10 :             QPdfWriter writer(path);
      42           5 :             writer.setCreator("QReports Library");
      43           5 :             writer.setTitle(m_report->getName());
      44           5 :             writer.setResolution(m_currentResolution);
      45          10 :             QPainter painter(&writer);
      46          10 :             QFont reportFont;
      47          10 :             QPen reportPen;
      48             : 
      49             :             // Настройка стилей. Стили считываются из отчета.
      50           5 :             auto &styles = m_report->getStyles();
      51           5 :             auto index = styles.begin();
      52           5 :             auto *style = (*index).data();
      53           5 :             reportFont.setFamily(style->getFontName());
      54           5 :             reportFont.setPointSize(style->getFontSize());
      55           5 :             style->isItalic() ? reportFont.setItalic(true) : reportFont.setItalic(false);
      56           5 :             style->isBold() ? reportFont.setBold(true) : reportFont.setBold(false);
      57           5 :             style->isUnderline() ? reportFont.setUnderline(true) : reportFont.setUnderline(false);
      58           5 :             style->isStrikeThrough() ? reportFont.setStrikeOut(true) : reportFont.setStrikeOut(false);
      59           5 :             reportPen.setColor(style->getFontColor());
      60             : 
      61           5 :             painter.setFont(reportFont);
      62           5 :             painter.setPen(reportPen);
      63             : 
      64          10 :             auto title = m_report->getTitle();
      65           5 :             if(!title.isNull())
      66             :             {
      67           2 :                 if(!createSection(writer, painter, title, 0))
      68             :                 {
      69           0 :                     m_lastError = "Report->Section is not created: title";
      70           0 :                     return false;
      71             :                 }
      72             :             }
      73             : 
      74          10 :             auto detail = m_report->getDetail();
      75           5 :             if(detail.isNull())
      76             :             {
      77           2 :                 m_lastError = "Report->Detail is empty";
      78           2 :                 return false;
      79             :             }
      80             : 
      81           3 :             if(!addGroupsIntoReport(writer, painter, m_report, detail))
      82           0 :                 return false;
      83             : 
      84           6 :             auto summary = m_report->getSummary();
      85           3 :             if(!summary.isNull())
      86             :             {
      87           2 :                 int lastField = m_report->getFieldsDataCount() - 1;
      88           2 :                 if(!createSection(writer, painter, summary, lastField))
      89             :                 {
      90           0 :                     m_lastError = "Report->Section is not created: summary";
      91           0 :                     return false;
      92             :                 }
      93             :             }
      94             : 
      95           3 :             painter.end();
      96           3 :             return true;
      97             : 
      98             :         }
      99             : 
     100          47 :         bool ConverterToPDF::createSection(QPdfWriter &writer, QPainter &painter, const SectionPtr &section, int i)
     101             :         {
     102          94 :             detail::Replacer replacer;
     103          47 :             if(!replacer.replace(section, m_report, i))
     104             :             {
     105           0 :                 m_lastError = "Error in replacing process: " + replacer.getLastError();
     106           0 :                 return false;
     107             :             }
     108             : 
     109          47 :             if(!createBands(writer, painter, section))
     110             :             {
     111           0 :                 m_lastError = "Error in creating bands process: " + replacer.getLastError();
     112           0 :                 return false;
     113             :             }
     114             : 
     115          47 :             return true;
     116             :         }
     117             : 
     118          47 :         bool ConverterToPDF::createBands(QPdfWriter &writer, QPainter &painter, const SectionPtr &section)
     119             :         {
     120         104 :             for(auto && band: section->getBands())
     121             :             {
     122          57 :                 if(m_currentHeight + band->getHeight() > m_report->getHeight())
     123             :                 {
     124          18 :                     writer.newPage();
     125          18 :                     m_currentHeight = 0;
     126             :                 }
     127             : 
     128         124 :                 for(auto && textField : band->getTextFields()) {
     129          67 :                     if(textField->getText() != "") {
     130          67 :                         Qt::AlignmentFlag alignment = Qt::AlignCenter;
     131          67 :                         if ((textField->getAlignment() & Qt::AlignLeft) == Qt::AlignLeft)
     132          54 :                             alignment = Qt::AlignLeft;
     133          67 :                         if ((textField->getAlignment() & Qt::AlignRight) == Qt::AlignRight)
     134          11 :                             alignment = Qt::AlignRight;
     135          67 :                         if ((textField->getAlignment() & Qt::AlignHCenter) == Qt::AlignHCenter)
     136           2 :                             alignment = Qt::AlignCenter;
     137          67 :                         if ((textField->getAlignment() & Qt::AlignJustify) == Qt::AlignJustify)
     138           0 :                             alignment = Qt::AlignJustify;
     139          67 :                         int x = textField->getX();
     140          67 :                         int y = textField->getY();
     141          67 :                         int w = textField->getWidth();
     142          67 :                         int h = textField->getHeight();
     143          67 :                         painter.drawText(x, y + m_currentHeight, w, h, alignment, textField->getText());
     144             :                     }
     145             :                 }
     146             : 
     147          77 :                 for(auto && staticText : band->getStaticTexts()) {
     148          20 :                     if(staticText->getText() != "") {
     149          20 :                         Qt::AlignmentFlag alignment = Qt::AlignCenter;
     150          20 :                         if ((staticText->getAlignment() & Qt::AlignLeft) == Qt::AlignLeft)
     151           7 :                             alignment = Qt::AlignLeft;
     152          20 :                         if ((staticText->getAlignment() & Qt::AlignRight) == Qt::AlignRight)
     153          12 :                             alignment = Qt::AlignRight;
     154          20 :                         if ((staticText->getAlignment() & Qt::AlignHCenter) == Qt::AlignHCenter)
     155           1 :                             alignment = Qt::AlignCenter;
     156          20 :                         if ((staticText->getAlignment() & Qt::AlignJustify) == Qt::AlignJustify)
     157           0 :                             alignment = Qt::AlignJustify;
     158             : 
     159          20 :                         int x = staticText->getX();
     160          20 :                         int y = staticText->getY();
     161          20 :                         int w = staticText->getWidth();
     162          20 :                         int h = staticText->getHeight();
     163          20 :                         painter.drawText(x, y + m_currentHeight, w, h, alignment, staticText->getText());
     164             :                     }
     165             :                 }
     166             : 
     167          69 :                 for(auto && image : band->getImages()) {
     168          24 :                     QImage img = image->getImage();
     169          12 :                     QRect imageRect;
     170          12 :                     imageRect.setX(image->getX());
     171          12 :                     imageRect.setY(image->getY());
     172          12 :                     imageRect.setWidth(image->getWidth());
     173          12 :                     imageRect.setHeight(image->getHeight());
     174          12 :                     painter.drawImage(imageRect, img);
     175             :                 }
     176             : 
     177          76 :                 for(auto && line : band->getLines()) {
     178          19 :                     int x1 = line->getX();
     179          19 :                     int y1 = line->getY() + m_currentHeight;
     180          19 :                     int x2 = x1 + line->getWidth() - 1;
     181          19 :                     int y2 = y1 + line->getHeight();
     182          19 :                     QLine qline(x1, y1, x2, y2);
     183          19 :                     painter.drawLine(qline);
     184             :                 }
     185             : 
     186          71 :                 for(auto && rect : band->getRects()) {
     187          14 :                     QRect rectC;
     188          14 :                     rectC.setX(rect->getRect().x());
     189          14 :                     rectC.setY(rect->getRect().y() + m_currentHeight);
     190          14 :                     rectC.setHeight(rect->getRect().height());
     191          14 :                     rectC.setWidth(rect->getRect().width());
     192          14 :                     painter.drawRect(rectC);
     193             :                 }
     194             : 
     195          69 :                 for(auto && ellipse : band->getEllipses()) {
     196          12 :                     QRect rectE;
     197          12 :                     rectE.setX(ellipse->getRect().x());
     198          12 :                     rectE.setY(ellipse->getRect().y() + m_currentHeight);
     199          12 :                     rectE.setHeight(ellipse->getRect().height());
     200          12 :                     rectE.setWidth(ellipse->getRect().width());
     201          12 :                     painter.drawEllipse(rectE);
     202             :                 }
     203             : 
     204          58 :                 for(auto && crosstab : band->getCrosstabs())
     205             :                 {
     206           2 :                     detail::Replacer replacer;
     207             : 
     208           2 :                     QList<QString> colGroups;
     209           1 :                     replacer.replaceColumnGroupsInCrosstab(crosstab, m_report, colGroups);
     210             : 
     211           2 :                     QList<QString> rowGroups;
     212           1 :                     replacer.replaceRowGroupsInCrosstab(crosstab, m_report, rowGroups);
     213             : 
     214           2 :                     QList<QString> cells;
     215           1 :                     replacer.replaceCellsInCrosstab(crosstab, m_report, cells);
     216             : 
     217           1 :                     QRect crosstabRect = crosstab->getRect();
     218             : 
     219           2 :                     auto rowGroup = crosstab->getRowGroup();
     220           2 :                     auto colGroup = crosstab->getColumnGroup();
     221           2 :                     auto cell     = crosstab->getCrosstabCell();
     222             : 
     223           1 :                     QRect emptyRect = QRect();
     224           1 :                     emptyRect.setX(crosstabRect.x());
     225           1 :                     emptyRect.setY(crosstabRect.y() + m_currentHeight);
     226           1 :                     emptyRect.setWidth(rowGroup->getWidth());
     227           1 :                     emptyRect.setHeight(cell->getHeight());
     228           1 :                     painter.drawRect(emptyRect);
     229             : 
     230           1 :                     int colX = crosstabRect.x() + rowGroup->getWidth();
     231           5 :                     for (int i = 0; i < colGroups.size(); i++)
     232             :                     {
     233           4 :                         Qt::AlignmentFlag alignment = Qt::AlignCenter;
     234           4 :                         if ((colGroup->getHeader()->getCellContents()->getAlignment() & Qt::AlignLeft) == Qt::AlignLeft)
     235           4 :                             alignment = Qt::AlignLeft;
     236           4 :                         if ((colGroup->getHeader()->getCellContents()->getAlignment() & Qt::AlignRight) == Qt::AlignRight)
     237           0 :                             alignment = Qt::AlignRight;
     238           4 :                         if ((colGroup->getHeader()->getCellContents()->getAlignment() & Qt::AlignHCenter) == Qt::AlignHCenter)
     239           0 :                             alignment = Qt::AlignCenter;
     240           4 :                         if ((colGroup->getHeader()->getCellContents()->getAlignment() & Qt::AlignJustify) == Qt::AlignJustify)
     241           0 :                             alignment = Qt::AlignJustify;
     242             : 
     243           4 :                         int x = colX + colGroup->getHeader()->getCellContents()->getTextField()->getX();
     244           4 :                         int y = crosstabRect.y() + colGroup->getHeader()->getCellContents()->getTextField()->getY();
     245           4 :                         int w = colGroup->getHeader()->getCellContents()->getTextField()->getWidth();
     246           4 :                         int h = colGroup->getHeader()->getCellContents()->getTextField()->getHeight();
     247           4 :                         painter.drawText(x, y + m_currentHeight, w, h, alignment, colGroups[i]);
     248             : 
     249           4 :                         QRect colRect = QRect();
     250           4 :                         colRect.setX(colX);
     251           4 :                         colRect.setY(crosstabRect.y() + m_currentHeight);
     252           4 :                         colRect.setWidth(cell->getWidth());
     253           4 :                         colRect.setHeight(colGroup->getHeight());
     254           4 :                         painter.drawRect(colRect);
     255             : 
     256           4 :                         colX += cell->getWidth();
     257             :                     }
     258             : 
     259           1 :                     int rowY = crosstabRect.y();
     260           5 :                     for (int i = 0; i < rowGroups.size(); i++)
     261             :                     {
     262           4 :                         rowY += cell->getHeight();
     263             : 
     264           4 :                         Qt::AlignmentFlag alignment = Qt::AlignCenter;
     265           4 :                         if ((rowGroup->getHeader()->getCellContents()->getAlignment() & Qt::AlignLeft) == Qt::AlignLeft)
     266           4 :                             alignment = Qt::AlignLeft;
     267           4 :                         if ((rowGroup->getHeader()->getCellContents()->getAlignment() & Qt::AlignRight) == Qt::AlignRight)
     268           0 :                             alignment = Qt::AlignRight;
     269           4 :                         if ((rowGroup->getHeader()->getCellContents()->getAlignment() & Qt::AlignHCenter) == Qt::AlignHCenter)
     270           0 :                             alignment = Qt::AlignCenter;
     271           4 :                         if ((rowGroup->getHeader()->getCellContents()->getAlignment() & Qt::AlignJustify) == Qt::AlignJustify)
     272           0 :                             alignment = Qt::AlignJustify;
     273             : 
     274           4 :                         int x = crosstabRect.x() + rowGroup->getHeader()->getCellContents()->getTextField()->getX();
     275           4 :                         int y = rowY + rowGroup->getHeader()->getCellContents()->getTextField()->getY();
     276           4 :                         int w = rowGroup->getHeader()->getCellContents()->getTextField()->getWidth();
     277           4 :                         int h = rowGroup->getHeader()->getCellContents()->getTextField()->getHeight();
     278           4 :                         painter.drawText(x, y + m_currentHeight, w, h, alignment, rowGroups[i]);
     279             : 
     280           4 :                         QRect rowRect = QRect();
     281           4 :                         rowRect.setX(crosstabRect.x());
     282           4 :                         rowRect.setY(rowY + m_currentHeight);
     283           4 :                         rowRect.setWidth(rowGroup->getWidth());
     284           4 :                         rowRect.setHeight(cell->getHeight());
     285           4 :                         painter.drawRect(rowRect);
     286             :                     }
     287             : 
     288           1 :                     int cellX = crosstabRect.x();
     289           1 :                     int cellY = crosstabRect.y();
     290           1 :                     int cellCount = 0;
     291           5 :                     for (int i = 0; i < rowGroups.size(); i++)
     292             :                     {
     293           4 :                         cellX += emptyRect.width();
     294           4 :                         cellY += emptyRect.height();
     295          20 :                         for(int j = 0; j < colGroups.size(); j++)
     296             :                         {
     297          16 :                             Qt::AlignmentFlag alignment = Qt::AlignCenter;
     298          16 :                             if ((cell->getCellContents()->getAlignment() & Qt::AlignLeft) == Qt::AlignLeft)
     299          16 :                                 alignment = Qt::AlignLeft;
     300          16 :                             if ((cell->getCellContents()->getAlignment() & Qt::AlignRight) == Qt::AlignRight)
     301           0 :                                 alignment = Qt::AlignRight;
     302          16 :                             if ((cell->getCellContents()->getAlignment() & Qt::AlignHCenter) == Qt::AlignHCenter)
     303           0 :                                 alignment = Qt::AlignCenter;
     304          16 :                             if ((cell->getCellContents()->getAlignment() & Qt::AlignJustify) == Qt::AlignJustify)
     305           0 :                                 alignment = Qt::AlignJustify;
     306             : 
     307          16 :                             int x = cellX + cell->getCellContents()->getTextField()->getX();
     308          16 :                             int y = cellY + cell->getCellContents()->getTextField()->getY();
     309          16 :                             int w = cell->getCellContents()->getTextField()->getWidth();
     310          16 :                             int h = cell->getCellContents()->getTextField()->getHeight();
     311          16 :                             painter.drawText(x, y + m_currentHeight, w, h, alignment, cells[cellCount]);
     312             : 
     313          16 :                             QRect cellRect = QRect();
     314          16 :                             cellRect.setX(cellX);
     315          16 :                             cellRect.setY(cellY + m_currentHeight);
     316          16 :                             cellRect.setWidth(cell->getWidth());
     317          16 :                             cellRect.setHeight(cell->getHeight());
     318          16 :                             painter.drawRect(cellRect);
     319             : 
     320          16 :                             cellCount++;
     321          16 :                             cellX += cell->getWidth();
     322             :                         }
     323           4 :                         cellX = crosstabRect.x();
     324             :                     }
     325             :                 }
     326             : 
     327          57 :                 m_currentHeight += band->getHeight();
     328             :             }
     329             : 
     330          47 :             return true;
     331             :         }
     332             : 
     333           5 :         const QString   ConverterToPDF::getLastError() const
     334             :         {
     335           5 :             return m_lastError;
     336             :         }
     337             : 
     338           3 :         bool ConverterToPDF::addGroupsIntoReport(QPdfWriter &writer, QPainter &painter, const ReportPtr &report, const DetailPtr &detail)
     339             :         {
     340           6 :             detail::Replacer replacer;
     341           6 :             QList<GroupPtr> groups = report->getGroups().values();
     342           6 :             QList<QString> groupNames;
     343             :             // Сюда помещаем конкретные имена по которым группируем
     344           6 :             QList<QString> particularNames;
     345           4 :             for(int i = 0; i < groups.length(); i++)
     346             :             {
     347           2 :                 auto groupExpression = groups[i]->getExpression();
     348           1 :                 if(groupExpression == "")
     349             :                 {
     350           0 :                     return false;
     351             :                 }
     352           1 :                 groupNames.append(groupExpression);
     353           1 :                 particularNames.append(replacer.replaceField(groupNames[i], report, 0));
     354             :             }
     355             : 
     356             :             // Открываем хедеры групп
     357           4 :             for(int i = 0; i < groups.length(); i++)
     358             :             {
     359           2 :                 auto header = groups[i]->getHeader();
     360           1 :                 if(!header.isNull())
     361             :                 {
     362           1 :                     if(!createSection(writer, painter, header, 0))
     363             :                     {
     364           0 :                         return false;
     365             :                     }
     366             :                 }
     367             :             }
     368             : 
     369           3 :             int rowCount = report->getRowCount();
     370          30 :             for(int i = 0; i < rowCount; i++)
     371             :             {
     372             :                 // Закрываем футеры, если группа закончилась
     373          38 :                 for(int j = groups.length() - 1; j >= 0; j--)
     374             :                 {
     375             :                     // Сверяем поле в заголовке и текущее поле
     376          11 :                     if(particularNames[j] != replacer.replaceField(groupNames[j], report, i))
     377             :                     {
     378          14 :                         auto footer = report->getGroupByIndex(j)->getFooter();
     379           7 :                         if(!footer.isNull())
     380             :                         {
     381           7 :                             if(!createSection(writer, painter, footer, i - 1))
     382             :                             {
     383           0 :                                 return false;
     384             :                             }
     385             :                         }
     386             :                     }
     387             :                 }
     388             :                 // Аналогично открываем хедеры
     389          38 :                 for(int j = 0; j < groupNames.length(); j++)
     390             :                 {
     391             :                     // Сверяем поле в заголовке и текущее поле
     392          11 :                     if(particularNames[j] != replacer.replaceField(groupNames[j], report, i))
     393             :                     {
     394          14 :                         auto header = report->getGroupByIndex(j)->getHeader();
     395           7 :                         if(!header.isNull())
     396             :                         {
     397           7 :                             if(!createSection(writer, painter, header, i))
     398             :                             {
     399           0 :                                 return false;
     400             :                             }
     401             :                         }
     402             :                     }
     403             :                 }
     404             :                 // Переписываем имена для сравнения
     405          38 :                 for(int j = 0; j < groupNames.length(); j++)
     406             :                 {
     407          11 :                     particularNames[j] = replacer.replaceField(groupNames[j], report, i);
     408             :                 }
     409             :                 // Выводим поле
     410          27 :                 if(!createSection(writer, painter, detail, i))
     411             :                 {
     412           0 :                     return false;
     413             :                 }
     414             :             }
     415             :             // Закрываем хедеры групп
     416           4 :             for(int i = groups.length() - 1; i >= 0; i--)
     417             :             {
     418           2 :                 auto footer = groups[i]->getFooter();
     419           1 :                 if(!footer.isNull())
     420             :                 {
     421           1 :                     if(!createSection(writer, painter, footer, (rowCount - 1)))
     422             :                     {
     423           0 :                         return false;
     424             :                     }
     425             :                 }
     426             :             }
     427           3 :             return true;
     428             :         }
     429             : 
     430             :     }
     431             : }

Generated by: LCOV version 1.14-2-gaa56a43