Line data Source code
1 : #include <QFrame>
2 : #include <QLabel>
3 : #include <QPainter>
4 : #include "utils/replacer.hpp"
5 : #include "convertertoqwidget.hpp"
6 : #include <QDebug>
7 :
8 : namespace qtreports
9 : {
10 : namespace detail
11 : {
12 :
13 13 : ConverterToQWidget::ConverterToQWidget( const ReportPtr & report ) :
14 : m_report( report ),
15 : m_type( WidgetType::Report ),
16 13 : m_currentHeight( 0 )
17 13 : {}
18 :
19 13 : ConverterToQWidget::~ConverterToQWidget() {}
20 :
21 6 : bool ConverterToQWidget::convert( WidgetType type )
22 : {
23 6 : m_type = type;
24 6 : return createQWidget( m_report );
25 : }
26 :
27 9 : bool ConverterToQWidget::isReport() const
28 : {
29 9 : return m_type == WidgetType::Report;
30 : }
31 :
32 594 : bool ConverterToQWidget::isLayout() const
33 : {
34 594 : return m_type == WidgetType::Layout;
35 : }
36 :
37 3 : ConverterToQWidget::WidgetType ConverterToQWidget::getType() const
38 : {
39 3 : return m_type;
40 : }
41 :
42 7 : const QWidgetPtr ConverterToQWidget::getQWidget() const
43 : {
44 7 : return m_qwidget;
45 : }
46 :
47 3 : const QWidgetPtr ConverterToQWidget::getPage( int i ) const
48 : {
49 3 : return m_pages.value( i );
50 : }
51 :
52 3 : const QVector< QWidgetPtr > ConverterToQWidget::getPages() const
53 : {
54 3 : return m_pages;
55 : }
56 :
57 5 : const QString ConverterToQWidget::getLastError() const
58 : {
59 5 : return m_lastError;
60 : }
61 :
62 21 : QHBoxLayout * createLayout( QWidget * left, QWidget * center, QWidget * right )
63 : {
64 21 : auto layout = new QHBoxLayout();
65 21 : layout->setMargin( 0 );
66 21 : layout->setSpacing( 0 );
67 :
68 21 : layout->addWidget( left );
69 21 : layout->addWidget( center );
70 21 : layout->addWidget( right );
71 :
72 21 : return layout;
73 : }
74 :
75 12 : void ConverterToQWidget::addVerticalBorder( QBoxLayout * parent, const QMargins & margins, int height )
76 : {
77 12 : auto leftFrame = new QFrame();
78 12 : leftFrame->setFixedWidth( margins.left() );
79 12 : leftFrame->setFixedHeight( height );
80 :
81 12 : auto centerFrame = new QFrame();
82 12 : centerFrame->setFixedHeight( height );
83 :
84 12 : auto rightFrame = new QFrame();
85 12 : rightFrame->setFixedWidth( margins.right() );
86 12 : rightFrame->setFixedHeight( height );
87 :
88 12 : if( isLayout() )
89 : {
90 4 : QString style = "border: 1px solid gray; ";
91 4 : leftFrame->setStyleSheet( style + "border-width: 0px 1px 0px 0px; " );
92 4 : rightFrame->setStyleSheet( style + "border-width: 0px 0px 0px 1px; " );
93 : }
94 :
95 12 : auto layout = createLayout( leftFrame, centerFrame, rightFrame );
96 12 : parent->addLayout( layout );
97 12 : }
98 :
99 6 : void ConverterToQWidget::addEmptySection( QBoxLayout * parent, const QMargins & margins )
100 : {
101 6 : auto leftFrame = new QFrame();
102 6 : leftFrame->setFixedWidth( margins.left() );
103 :
104 6 : auto centerFrame = new QFrame();
105 :
106 6 : auto rightFrame = new QFrame();
107 6 : rightFrame->setFixedWidth( margins.right() );
108 :
109 6 : if( isLayout() )
110 : {
111 2 : QString style = "border: 1px solid gray; ";
112 2 : leftFrame->setStyleSheet( style + "border-width: 1px 1px 1px 0px; " );
113 2 : centerFrame->setObjectName( "frame" );
114 2 : centerFrame->setStyleSheet( "#frame{" + style + "border-width: 1px 0px 1px 0px; }" );
115 2 : rightFrame->setStyleSheet( style + "border-width: 1px 0px 1px 1px; " );
116 : }
117 :
118 6 : auto layout = createLayout( leftFrame, centerFrame, rightFrame );
119 6 : parent->addLayout( layout );
120 6 : }
121 :
122 3 : QFrame * ConverterToQWidget::addSectionLayout( QBoxLayout * parent, const QMargins & margins, int height )
123 : {
124 3 : auto leftFrame = new QFrame();
125 3 : leftFrame->setFixedHeight( height );
126 3 : leftFrame->setFixedWidth( margins.left() );
127 :
128 3 : auto centerFrame = new QFrame();
129 3 : centerFrame->setFixedHeight( height );
130 :
131 :
132 :
133 3 : auto rightFrame = new QFrame();
134 3 : rightFrame->setFixedHeight( height );
135 3 : rightFrame->setFixedWidth( margins.right() );
136 :
137 3 : if( isLayout() )
138 : {
139 3 : QString style = "border: 1px solid gray; ";
140 3 : leftFrame->setStyleSheet( style + "border-width: 1px 1px 0px 0px; " );
141 3 : centerFrame->setObjectName( "frame" );
142 3 : centerFrame->setStyleSheet( "#frame{" + style + "border-width: 1px 0px 0px 0px; }" );
143 3 : rightFrame->setStyleSheet( style + "border-width: 1px 0px 0px 1px; " );
144 : }
145 :
146 3 : auto layout = createLayout( leftFrame, centerFrame, rightFrame );
147 3 : parent->addLayout( layout );
148 :
149 3 : return centerFrame;
150 : }
151 :
152 41 : void ConverterToQWidget::addPage()
153 : {
154 41 : QWidgetPtr widget( new QWidget() );
155 41 : widget->resize( m_report->getSize() );
156 41 : widget->setStyleSheet( "background-color: white; " );
157 41 : m_pages.append( widget );
158 41 : }
159 :
160 6 : bool ConverterToQWidget::createQWidget( const ReportPtr & report )
161 : {
162 6 : if( report.isNull() )
163 : {
164 0 : m_lastError = "Report is empty";
165 0 : return false;
166 : }
167 :
168 6 : auto detail = report->getDetail();
169 6 : if( detail.isNull() )
170 : {
171 0 : m_lastError = "Report->Detail is empty";
172 0 : return false;
173 : }
174 :
175 6 : m_qwidget = QWidgetPtr( new QWidget() );
176 6 : m_qwidget->setStyleSheet( "background-color: white; " );//border: 1px solid gray;
177 : //m_qwidget->setContentsMargins( m_report->getMargins() );
178 :
179 6 : addPage();
180 :
181 6 : auto layout = new QVBoxLayout( m_qwidget.data() );
182 6 : layout->setMargin( 0 );
183 6 : layout->setSpacing( 0 );
184 6 : addVerticalBorder( layout, report->getMargins(), report->getTopMargin() );
185 :
186 12 : auto title = report->getTitle();
187 6 : if( !title.isNull() )
188 : {
189 3 : QWidget * sectionWidget = isLayout() ? addSectionLayout( layout, report->getMargins(), title->getHeight() ) : nullptr;
190 3 : if( !createSection( sectionWidget, title, 0 ) )
191 : {
192 0 : return false;
193 : }
194 : }
195 :
196 6 : if(!addGroupsIntoReport(report, detail, layout))
197 0 : return false;
198 :
199 6 : addEmptySection( layout, report->getMargins() );
200 6 : addVerticalBorder( layout, report->getMargins(), report->getBottomMargin() );
201 12 : return true;
202 : }
203 :
204 6 : bool ConverterToQWidget::addGroupsIntoReport(const ReportPtr & report, const DetailPtr & detail, QVBoxLayout* layout)
205 : {
206 6 : detail::Replacer replacer;
207 :
208 12 : QList<GroupPtr> groups = report->getGroups().values();
209 12 : QList<QString> groupNames;
210 : //Сюда помещаем конкретные имена по которым группируем
211 6 : QString *particularNames = new QString[groups.length()];
212 6 : for (int i = 0; i<groups.length(); i++)
213 : {
214 0 : groupNames.append(groups[i]
215 : ->getHeader()
216 : ->getBand(0)
217 : ->getTextField(0)
218 0 : ->getOriginalText());
219 0 : particularNames[i] = replacer.replaceField(groupNames[i], report, 0);
220 : }
221 : //Открываем хедеры групп
222 6 : for (int i = 0; i<groups.length(); i++)
223 : {
224 0 : auto header = groups[i]->getHeader();
225 0 : if (!header.isNull())
226 : {
227 0 : QWidget * sectionWidget = isLayout() ? addSectionLayout(layout, report->getMargins(), header->getHeight()) : nullptr;
228 0 : if (!createSection(sectionWidget, header, 0))
229 : {
230 0 : return false;
231 : }
232 : }
233 0 : }
234 :
235 6 : int rowCount = isReport()? report->getRowCount() : 1;
236 38 : for(int i = 0; i < rowCount; i++)
237 : {
238 32 : QWidget * sectionWidget = isLayout() ? sectionWidget = addSectionLayout(layout, report->getMargins(), detail->getHeight()) : nullptr;
239 :
240 : //Закрываем футеры, если группа закончилась
241 32 : for(int j = groups.length() - 1; j >= 0; j--)
242 : {
243 : //сверяем поле в заголовке и текущее поле
244 0 : if(particularNames[j] != replacer.replaceField(groupNames[j], report, i))
245 : {
246 0 : auto footer = report->getGroupByIndex(j)->getFooter();
247 0 : if (!footer.isNull())
248 : {
249 0 : QWidget * sectionWidgetFooter = isLayout() ? addSectionLayout(layout, report->getMargins(), footer->getHeight()) : nullptr;
250 0 : if (!createSection(sectionWidgetFooter, footer, i - 1))
251 : {
252 0 : return false;
253 : }
254 0 : }
255 : }
256 : }
257 : //Аналогично открываем хедеры
258 32 : for(int j = 0; j < groupNames.length(); j++)
259 : {
260 : //сверяем поле в заголовке и текущее поле
261 0 : if(particularNames[j] != replacer.replaceField(groupNames[j], report, i))
262 : {
263 0 : auto header = report->getGroupByIndex(j)->getHeader();
264 0 : if (!header.isNull())
265 : {
266 0 : QWidget * sectionWidgetHeader = isLayout() ? addSectionLayout(layout, report->getMargins(), header->getHeight()) : nullptr;
267 0 : if (!createSection(sectionWidgetHeader, header, i))
268 : {
269 0 : return false;
270 : }
271 0 : }
272 : }
273 : }
274 : //Переписываем имена для сравнения
275 32 : for(int j = 0; j < groupNames.length(); j++)
276 : {
277 0 : particularNames[j] = replacer.replaceField(groupNames[j], report, i);
278 : }
279 : //Выводим поле
280 32 : if (!createSection(sectionWidget, detail, i))
281 : {
282 0 : return false;
283 : }
284 : }
285 : //Закрываем хедеры групп
286 6 : for(int i = groups.length() - 1; i >= 0; i--)
287 : {
288 0 : auto footer = groups[i]->getFooter();
289 0 : if (!footer.isNull())
290 : {
291 0 : QWidget * sectionWidget = isLayout() ? addSectionLayout(layout, report->getMargins(), footer->getHeight()) : nullptr;
292 0 : if (!createSection(sectionWidget, footer, (rowCount - 1)))
293 : {
294 0 : return false;
295 : }
296 : }
297 0 : }
298 12 : return true;
299 : }
300 :
301 :
302 35 : bool ConverterToQWidget::createSection( QWidget * parent, const SectionPtr & section, int i )
303 : {
304 35 : if( isLayout() )
305 : {
306 3 : auto label = new QLabel( parent );
307 3 : label->setText( section->getTagName() );
308 3 : label->setStyleSheet( "font-size: 26px; color: gray" );
309 3 : label->setAlignment( Qt::AlignCenter );
310 3 : label->setAttribute( Qt::WA_TranslucentBackground );
311 3 : label->resize( parent->size() );
312 : }
313 : else
314 : {
315 32 : detail::Replacer replacer;
316 32 : if( !replacer.replace( section, m_report, i ) )
317 : {
318 0 : m_lastError = "Error in replacing process: " + replacer.getLastError();
319 0 : return false;
320 32 : }
321 : }
322 :
323 35 : if( !createBands( parent, section ) )
324 : {
325 0 : return false;
326 : }
327 :
328 35 : return true;
329 : }
330 :
331 35 : bool ConverterToQWidget::createBands( QWidget * parent, const SectionPtr & section )
332 : {
333 35 : auto dy = 0;
334 116 : for( auto && band : section->getBands() )
335 : {
336 81 : if( m_currentHeight + band->getHeight() > m_report->getHeight() )
337 : {
338 35 : addPage();
339 35 : m_currentHeight = 0;
340 : }
341 :
342 81 : auto frame = new QFrame( isLayout() ? parent : m_pages.last().data() );
343 81 : frame->setStyleSheet( "background-color: transparent; " );
344 81 : frame->move( frame->x(), isLayout() ? dy : m_currentHeight );
345 :
346 81 : m_currentHeight += band->getHeight();
347 81 : dy += band->getHeight();
348 :
349 224 : for( auto && textWidget : band->getTextWidgets() )
350 : {
351 143 : auto label = new QLabel( frame );
352 143 : QString style = "";
353 143 : if( textWidget->isBold() )
354 : {
355 98 : style += "font-weight: bold; ";
356 : }
357 143 : if( isLayout() )
358 : {
359 11 : style += "border: 1px solid gray; ";
360 : }
361 143 : label->setStyleSheet( "background-color: transparent; " + style );
362 143 : label->setGeometry( textWidget->getRect() );
363 143 : label->setAlignment( textWidget->getAlignment() );
364 286 : auto text = isLayout() ? textWidget->getOriginalText() : textWidget->getText();
365 143 : label->setText( text );
366 224 : }
367 107 : for( auto && line : band->getLines() )
368 : {
369 26 : auto label = new QLabel( frame );
370 26 : QString style = "";
371 26 : if( line->isBold() )
372 : {
373 26 : style += "font-weight: bold; ";
374 : }
375 : //if( isLayout() )
376 : {
377 26 : style += "border: 1px solid gray; ";
378 : }
379 26 : label->setStyleSheet( "background-color: transparent; " + style );
380 26 : label->setGeometry( line->getRect() );
381 26 : label->setAlignment( line->getAlignment() );
382 : //label->setText( "----------------------" );
383 107 : }
384 107 : for( auto && imageWidget : band->getImages() )
385 : {
386 26 : if( imageWidget->getRect().isEmpty() )
387 : {
388 0 : m_lastError = "Ellipse \"" + imageWidget->getName() + "\" rect is empty";
389 0 : return false;
390 : }
391 :
392 26 : auto label = new QLabel( frame );
393 26 : QString style = "";
394 26 : if( isLayout() )
395 : {
396 2 : style += "border: 1px solid gray; ";
397 : }
398 26 : label->setStyleSheet( "background-color: transparent; " + style );
399 26 : label->setGeometry( imageWidget->getRect() );
400 26 : label->setAlignment( imageWidget->getAlignment() );
401 26 : label->setPixmap( QPixmap::fromImage( imageWidget->getImage() ) );
402 107 : }
403 107 : for( auto && rect : band->getRects() )
404 : {
405 26 : if( rect->getRect().isEmpty() )
406 : {
407 0 : m_lastError = "Rect \"" + rect->getName() + "\" rect is empty";
408 0 : return false;
409 : }
410 :
411 26 : auto label = new QLabel( frame );
412 26 : QString style = "";
413 26 : if( rect->isBold() )
414 : {
415 26 : style += "font-weight: bold; ";
416 : }
417 : //if( isLayout() )
418 : {
419 26 : style += "border: 1px solid gray; ";
420 : }
421 26 : label->setStyleSheet( "background-color: transparent; " + style );
422 26 : label->setGeometry( rect->getRect() );
423 26 : label->setAlignment( rect->getAlignment() );
424 : //label->setText( "----------------------" );
425 107 : }
426 107 : for( auto && ellipse : band->getEllipses() )
427 : {
428 26 : if( ellipse->getSize().isEmpty() )
429 : {
430 0 : m_lastError = "Ellipse \"" + ellipse->getName() + "\" size is empty";
431 0 : return false;
432 : }
433 :
434 26 : auto label = new QLabel( frame );
435 26 : QString style = "";
436 26 : if( isLayout() )
437 : {
438 2 : style += "border: 1px solid gray; ";
439 : }
440 :
441 52 : QPixmap pixmap( ellipse->getSize() );
442 26 : pixmap.fill( Qt::GlobalColor::transparent );
443 :
444 52 : QPainter painter( &pixmap );
445 26 : painter.setRenderHint( QPainter::Antialiasing );
446 26 : painter.drawEllipse( ellipse->getRect() );
447 26 : painter.end();
448 26 : label->setPixmap( pixmap );
449 :
450 26 : label->setStyleSheet( "background-color: transparent; " + style );
451 26 : label->setGeometry( ellipse->getRect() );
452 26 : label->setAlignment( ellipse->getAlignment() );
453 107 : }
454 35 : }
455 :
456 35 : return true;
457 : }
458 :
459 : }
460 : }
|