/* class N { static int& nref() { static int n = 0; return n; } public: N() {nref()++;} ~N() {nref()--;} operator int() const {return nref();} }; */ ReportItem::PrintResult ReportItemFrame::printMetaPaintChildren(ReportItemMetaPaint *out, const ReportItem::Rect &bounding_rect) { qfLogFuncFrame();// << element.tagName() << "id:" << element.attribute("id") << "itemCount:" << itemsToPrintCount() << "indexToPrint:" << indexToPrint; qfDebug() << "\tbounding_rect:" << bounding_rect.toString(); //N n; //QF_TIME_SCOPE(QString::number((int)n) + ": ReportItemFrame::printMetaPaintChildren"); PrintResult res = PR_PrintedOk; Rect paint_area_rect = bounding_rect; if(layout() == LayoutStacked) { /// allways print all the children) in the stacked layout /// it is used mainly for page header & footers, they shoud be on each page //Rect rendered_rect; for(m_indexToPrint=0; m_indexToPrint<itemsToPrintCount(); m_indexToPrint++) { ReportItem *it = itemToPrintAt(m_indexToPrint); Rect children_paint_area_rect = paint_area_rect; ChildSize sz = it->childSize(LayoutVertical); children_paint_area_rect.setHeight(sz.fromParentSize(paint_area_rect.height())); PrintResult ch_res = it->printMetaPaint(out, children_paint_area_rect); if(ch_res == PR_PrintAgainOnNextPage) { if(res == PR_PrintedOk) { /// only one child can be printed again /// others are ignored in ch_res flags res = ch_res; } } else { // print item again on new page it->resetIndexToPrintRecursively(true); } //qfInfo() << indexToPrint << "ch res:" << ch_res.toString() << "res:" << res.toString(); } } else if(layout() == LayoutHorizontal) { /// Break is ignored in horizontal layout QList<ChildSize> layout_sizes; m_indexToPrint = 0; /// allways print from 0 index (all the children) in horizontal layout /// horizontalni layout musi mit procenta rozpocitany dopredu, protoze jinak by se mi nezalamovaly texty v tabulkach { /// get layout sizes in the layout direction for(int i=m_indexToPrint; i<itemsToPrintCount(); i++) { ReportItem *it = itemToPrintAt(i); layout_sizes << it->childSize(layout()); } } /// get layout sizes in the orthogonal layout direction /// je to bud absolutni hodnota nebo % z bbr QList<ChildSize> orthogonal_sizes; for(int i=m_indexToPrint; i<itemsToPrintCount(); i++) { ReportItem *it = itemToPrintAt(i); Layout ol = orthogonalLayout(); ChildSize sz = it->childSize(ol); if(sz.unit == Rect::UnitPercent) { sz.size = paint_area_rect.sizeInLayout(ol); /// udelej z nej rubber, roztahne se dodatecne } orthogonal_sizes << sz; } /// Items should be printed in special order to make proper layout of all the kinds of size specifiers (xx, undefined, "xx%") /// in horizontal layout, print fixed mm size width items first, the rubber (without width specified) ones as second, rest of space divide according to % value /// when printed, rearange printed items to their original layout order QMap<int, int> layout_ix_to_print_ix; /// layout_ix->print_ix qreal sum_mm = 0; bool has_percent = false; /// print rubber and fixed for(int i=0; i<itemsToPrintCount(); i++) { ReportItem *it = itemToPrintAt(i); ChildSize sz = layout_sizes.value(i); //qfInfo() << "child:" << i << "size:" << sz.size << "unit:" << Rect::unitToString(sz.unit); if(sz.unit == Rect::UnitMM) { Rect ch_bbr = paint_area_rect; ch_bbr.setLeft(paint_area_rect.left() + sum_mm); if(sz.size > 0) ch_bbr.setWidth(sz.size); else ch_bbr.setWidth(paint_area_rect.width() - sum_mm); if(orthogonal_sizes[i].size > 0) { ch_bbr.setSizeInLayout(orthogonal_sizes[i].size, orthogonalLayout()); } //qfInfo() << "\t tisknu fixed:" << it->designedRect.toString(); int prev_children_cnt = out->childrenCount(); PrintResult ch_res = it->printMetaPaint(out, ch_bbr); if(out->children().count() > prev_children_cnt) { //qfInfo() << "rubber fixed:" << i << "->" << prev_children_cnt; layout_ix_to_print_ix[i] = prev_children_cnt; double width = out->lastChild()->renderedRect.width(); sum_mm += width; //qfInfo() << "\t sum_mm:" << sum_mm; if(ch_res == PR_PrintAgainOnNextPage) { /// para can be printed as NotFit if it owerflows its parent frame res = ch_res; } } else { if(ch_res == PR_PrintedOk) { /// jediny, kdo se nemusi vytisknout je band if(it->isVisible()) { qfWarning() << "jak to, ze se dite nevytisklo v horizontalnim layoutu?" << it; } } else { //qfInfo() << "\t NOT OK"; res = ch_res; break; } } } else { has_percent = true; } } qreal rest_mm = paint_area_rect.width() - sum_mm; if(res == PR_PrintedOk) { if(has_percent) { /// divide rest of space to xx% items qreal sum_percent = 0; int cnt_0_percent = 0; for(int i=0; i<itemsToPrintCount(); i++) { ReportItem *it = itemToPrintAt(i); ChildSize sz = it->childSize(layout()); if(sz.unit == Rect::UnitPercent) { if(sz.size == 0) cnt_0_percent++; else sum_percent += sz.size; } } if(rest_mm <= 0) { qfWarning() << "Percent exist but rest_mm is" << rest_mm << ". Ignoring rest of frames"; } else { /// print percent items qreal percent_0 = 0; if(cnt_0_percent > 0) percent_0 = (100 - sum_percent) / cnt_0_percent; for(int i=0; i<itemsToPrintCount(); i++) { ReportItem *it = itemToPrintAt(i); ChildSize sz = it->childSize(layout()); if(sz.unit == Rect::UnitPercent) { qreal d; if(sz.size == 0) d = rest_mm * percent_0 / 100; else d = rest_mm * sz.size / 100; //qfInfo() << d; Rect ch_bbr = paint_area_rect; ch_bbr.setWidth(d); if(orthogonal_sizes[i].size > 0) { ch_bbr.setSizeInLayout(orthogonal_sizes[i].size, orthogonalLayout()); } //qfInfo() << it << "tisknu percent" << it->designedRect.toString(); //qfInfo() << "chbr" << ch_bbr.toString(); int prev_children_cnt = out->childrenCount(); PrintResult ch_res = it->printMetaPaint(out, ch_bbr); if(out->children().count() > prev_children_cnt) { //qfInfo() << "percent:" << i << "->" << prev_children_cnt; layout_ix_to_print_ix[i] = prev_children_cnt; if(ch_res == PR_PrintAgainOnNextPage) { /// para se muze vytisknout a pritom bejt not fit, pokud pretece res = ch_res; } } else { if(ch_res == PR_PrintedOk) { /// jediny, kdo se nemusi vytisknout je band if(it->isVisible()) { qfWarning() << "jak to, ze se dite nevytisklo v horizontalnim layoutu?" << it; } } else { res = ch_res; break; } } } } } /// arrange prited children to their original order //qfInfo() << "\t poradi tisku cnt:<<" << poradi_tisku.count() << out->childrenCount(); if(layout_ix_to_print_ix.count() == out->children().count()) { int children_count = out->children().count(); //qfInfo() << "children cnt:" << children_count; //QF_ASSERT(poradi_tisku.count() == out->children().count(), "nevytiskly se vsechny deti v horizontalnim layoutu"); QVector<qf::core::utils::TreeItemBase*> old_children(layout_ix_to_print_ix.count()); /// get printed children pointers for(int i=0; i<children_count; i++) old_children[i] = out->children()[i]; /// arrange them to the original order /// v mape nemusi byt rada klicu souvisla (kdyz se nejake dite nevytiskne) QMapIterator<int, int> iter(layout_ix_to_print_ix); int new_print_ix = 0; while(iter.hasNext()) { iter.next(); int old_print_ix = iter.value(); if(0 <= new_print_ix && new_print_ix < children_count) { //qfInfo() << old_print_ix << "->" << new_print_ix; if(new_print_ix != old_print_ix) out->childrenRef()[new_print_ix] = old_children[old_print_ix]; new_print_ix++; } else qfWarning() << QF_FUNC_NAME << "order:" << old_print_ix << "new_ix:" << new_print_ix << "out of range:" << children_count; } /// set children proper offsets qreal offset_x = 0; for(int i=0; i<layout_ix_to_print_ix.count(); i++) { //qfInfo() << "\t poradi tisku <<" << i << "offset:" << offset_x; ReportItemMetaPaint *it = out->child(i); /// shift them including their own children recursively :( double shift_x = paint_area_rect.left() + offset_x - it->renderedRect.left(); //if(parent_grid) qfInfo() << i << "offset_x:" << offset_x << "bbr left:" << bbr.left() << "chbbr left:" << ch_bbr.left(); if(qFloatDistance(shift_x, 0) > 200) it->shift(Point(shift_x, 0)); offset_x += it->renderedRect.width(); } } else { qfWarning() << this << "nesedi poradi pocty tisku" << layout_ix_to_print_ix.count() << out->children().count(); } } } if(res == PR_PrintAgainOnNextPage) { /// detail by mel mit, pokud se ma zalamovat, vzdy vertikalni layout, jinak tato funkce zpusobi, ze se po zalomeni vsechny dcerine bandy budou tisknout cele znova /// zakomentoval jsem to a zda se, ze to zatim nicemu nevadi //resetIndexToPrintRecursively(!ReportItem::IncludingParaTexts); } } else { /// vertical layout /// print % like a rubber dimension and if print result is PrintOk resize rendered rect of printed metapaint item /// break funguje tak, ze pri 1., 3., 5. atd. tisku vraci PrintNotFit a pri sudych PrintOk /// prvni break na strance znamena, ze jsem tu uz po zalomeni, takze se tiskne to za break. int index_to_print_0 = m_indexToPrint; for(; m_indexToPrint<itemsToPrintCount(); m_indexToPrint++) { ReportItem *child_item_to_print = itemToPrintAt(m_indexToPrint); Rect children_paint_area_rect = paint_area_rect; qfDebug() << "\tch_bbr v1:" << children_paint_area_rect.toString(); { /// find child paint area size in layout direction qreal d = children_paint_area_rect.sizeInLayout(layout()); ChildSize sz = child_item_to_print->childSize(layout()); //qfInfo() << it << "chbrd:" << ch_bbr.toString() << "d:" << d;// << "size in ly:" << sz.fillLayoutRatio(); if(sz.fillLayoutRatio() >= 0) { } else if(sz.unit == Rect::UnitMM) { if(sz.size > 0) d = sz.size; } else { ReportItemFrame *frit = qobject_cast<ReportItemFrame*>(child_item_to_print); if(frit) qfWarning() << "This should never happen" << child_item_to_print; } //qfInfo() << "\t ch_bbr.sizeInLayout(layout():" << ch_bbr.sizeInLayout(layout()) << "d:" << d; d = qMin(children_paint_area_rect.sizeInLayout(layout()), d); children_paint_area_rect.setSizeInLayout(d, layout()); //qfInfo() << "\t ch_bbr:" << ch_bbr.toString(); } { /// orthogonal size Layout ol = orthogonalLayout(); ChildSize o_sz = child_item_to_print->childSize(ol); if(o_sz.unit == Rect::UnitPercent) { if(o_sz.size == 0) o_sz.size = paint_area_rect.sizeInLayout(ol); else o_sz.size = o_sz.size / 100 * paint_area_rect.sizeInLayout(ol); } //it->metaPaintOrthogonalLayoutLength = sz.size; qfDebug() << "\tsetting orthogonal length:" << o_sz.size; //if(it->isBreak() && i > indexToPrint && layout == LayoutVertical) break; /// v horizontalnim layoutu break ignoruj if(o_sz.size > 0) { children_paint_area_rect.setSizeInLayout(o_sz.size, orthogonalLayout()); } } qfDebug() << "\tch_bbr v2:" << children_paint_area_rect.toString(); int prev_children_cnt = out->childrenCount(); PrintResult ch_res = child_item_to_print->printMetaPaint(out, children_paint_area_rect); if(ch_res == PR_PrintedOk || ch_res == PR_PrintAgainDetail) { /// muze se stat, ze se dite nevytiskne, napriklad band nema zadna data if(out->children().count() > prev_children_cnt) { ReportItemMetaPaint *mpi = out->lastChild(); if(mpi) { const Rect &r = mpi->renderedRect; /// cut rendered area paint_area_rect.cutSizeInLayout(r, layout()); if(ch_res == PR_PrintAgainDetail) { m_indexToPrint--; /// vytiskni ho znovu } } } } else { /// pokud je vertikalni layout, a dite se nevejde vrat PrintNotFit res = ch_res; break; } if(child_item_to_print->isBreak() && m_indexToPrint > index_to_print_0) break; } } //res = checkPrintResult(res); qfDebug() << "\t<<< CHILDREN return:" << res.toString(); return res; }