Ejemplo n.º 1
0
ReportItem::PrintResult ReportItemBand::printMetaPaint(ReportItemMetaPaint *out, const ReportItem::Rect &bounding_rect)
{
	qfLogFuncFrame() << this;
	if(isCreateFromData() && !detail()) {
		createChildItemsFromData();
	}
	//qfInfo() << dataTable().toString();
	/*--
	if(dataTable().isNull() && !processor()->isDesignMode()) { /// pokud neni table (treba bez radku), band se vubec netiskne
		PrintResult res;
		res.value = PrintOk;
		return res;
	}
	--*/
	if(isHeaderOnBreak()) {
		/// print everything except of detail again
		ReportItemDetail *it_det = detail();
		if(it_det)
			it_det->resetIndexToPrintRecursively(ReportItem::IncludingParaTexts);
		indexToPrint = 0;
	}
	PrintResult res = Super::printMetaPaint(out, bounding_rect);
	qfDebug() << "\tRETURN:" << res.toString();
	return res;
}
Ejemplo n.º 2
0
ReportItem::PrintResult ReportItemBand::printMetaPaint(ReportItemMetaPaint *out, const Rect &bounding_rect)
{
	qfLogFuncFrame() << this;
	//qfInfo() << dataTable().toString();
	/*--
	if(dataTable().isNull() && !processor()->isDesignMode()) { /// pokud neni table (treba bez radku), band se vubec netiskne
		PrintResult res;
		res.value = PrintOk;
		return res;
	}
	--*/
	if(isHeaderOnBreak()) {
		/// print everything except of detail again
		for(int i=0; i<itemCount(); i++) {
			ReportItem *it = itemAt(i);
			if(it->toDetail() == NULL)
				it->resetIndexToPrintRecursively(ReportItem::IncludingParaTexts);
		}
		indexToPrint = 0;
	}
	PrintResult res = ReportItemFrame::printMetaPaint(out, bounding_rect);
	qfDebug() << "\tRETURN:" << res.toString();
	return res;
}
Ejemplo n.º 3
0
ReportItem::PrintResult ReportItemPara::printMetaPaintChildren(ReportItemMetaPaint *out, const ReportItem::Rect &bounding_rect)
{
	qfLogFuncFrame() << this << bounding_rect.toString();
	PrintResult res = PR_PrintedOk;
	if(m_indexToPrint == 0) {
		printedText = paraText();
	}
	//qfInfo() << printedText;
	QString text = printedText.mid(m_indexToPrint);
	int initial_index_to_print = m_indexToPrint;

	QString sql_id = sqlId();
	/// tiskne se prazdny text
	bool omit_empty_text = isOmitEmptyText();
	if(text.isEmpty() && omit_empty_text) {
	}
	else {
		QString text_to_layout = text;
		//qfWarning() << "length: " << text.length() << " text: [" << text << "]\n" << text.toUtf8().toHex();
		bool text_item_should_be_created = true;
		style::CompiledTextStyle style;
		style::Text *p_text_style = effectiveTextStyle();
		if(p_text_style) {
			style = p_text_style->textStyle();
		}
		QFontMetricsF font_metrics = processor()->fontMetrics(style.font());
		QTextOption text_option;
		{
			if(isTextWrap())
				text_option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
			//alignment_flags |= Qt::TextWordWrap;
			int al = textHAlign() | textVAlign();
			Qt::Alignment alignment_flags = (Qt::Alignment)al;
			text_option.setAlignment(alignment_flags);
		}
		Rect rendered_bounding_rect;
		/// velikost boundingRect je v mm, tak to prepocitej na body vystupniho zarizeni
		rendered_bounding_rect = qmlwidgets::graphics::mm2device(bounding_rect, processor()->paintDevice());

		bool render_check_mark = false;
		QRegExp rx = ReportItemMetaPaint::checkReportSubstitutionRegExp;
		if(rx.exactMatch(text_to_layout)) {
			//bool check_on = rx.capturedTexts().value(1) == "1";
			rendered_bounding_rect = font_metrics.boundingRect('X');
			render_check_mark = true;
			m_indexToPrint += text_to_layout.length();
		}
		else {
			if(text_to_layout.isEmpty()) {
				/// neni omitEmptyString, takze i prazdnej text vyrendruj alespon jako mezeru aby se na to dalo treba kliknout
				text_to_layout = ' ';
			}

			//text.replace(ReportItemMetaPaint::checkOnReportSubstitution, "X");
			//text.replace(ReportItemMetaPaint::checkOffReportSubstitution, "X");
			//qfInfo().noSpace().color(QFLog::Green) << "index to print: " << indexToPrint << " text: '" << text << "'";
			//qfInfo() << "bounding rect:" << bounding_rect.toString();
			//qfWarning() << "device physical DPI:" << processor()->paintDevice()->physicalDpiX() << processor()->paintDevice()->physicalDpiY();
			//qfWarning().noSpace() << "'" << text << "' font metrics: " << br.toString();

			//QString text = element.text().simplified().replace("\\n", "\n");
			//qfInfo() << "br:" << br.toString();
			//Rect br_debug = br;
			//bool splitted = false;
			/// do layout
			{
				qreal leading = font_metrics.leading();
				qreal height = 0;
				qreal width = 0;
				textLayout.setFont(style.font());
				textLayout.setTextOption(text_option);
				textLayout.setText(text_to_layout);
				textLayout.beginLayout();
				bool finished = false;
				while (!finished) {
					QTextLine line = textLayout.createLine();
					finished = !line.isValid();
					if(!finished) {
						line.setLineWidth(rendered_bounding_rect.width()); /// setWidth() nastavi spravne line.height(), proto musi byt pred merenim popsane vysky.

						if((line.textLength() == 0) && (line.textStart() + line.textLength() == text_to_layout.length())) {
							/// nevim kde je chyba, pri vicerakovych textech mi to pridava jeden prazdnej radek na konec, takhle se tomu snazim zabranit (Qt 4.6.3)
							finished = true;
						}
						else {
							qreal interline_space = (height > 0)? leading: 0;
							if(height + interline_space + line.height() > rendered_bounding_rect.height()) {
								res = PR_PrintAgainOnNextPage;
								if(height == 0) {
									/// nevejde se ani jeden radek
									text_item_should_be_created = false;
									break;
								}
								else {
									/// neco se preci jenom veslo
									int pos = line.textStart();
									m_indexToPrint += pos;
									break;
								}
							}
							height += interline_space;
							line.setPosition(QPointF(0., height));
							height += line.height();
							width = qMax(width, line.naturalTextWidth());
						}
					}
					if(finished) {
						m_indexToPrint = printedText.length();
					}
				}
				textLayout.endLayout();
				rendered_bounding_rect.setWidth(width);
				rendered_bounding_rect.setHeight(height);
			}
		}
		/// velikost boundingRect je v bodech vystupniho zarizeni, tak to prepocitej na mm
		rendered_bounding_rect = qmlwidgets::graphics::device2mm(rendered_bounding_rect, processor()->paintDevice());
		/// rendered rect is left aligned, if text is reight aligned or centered, the ReportItemMetaPaintText::paint() does it
		if(text_item_should_be_created ) {
			ReportItemMetaPaintText *mt;
			if(render_check_mark )
				mt = new ReportItemMetaPaintCheck(out, this);
			else {
				mt = new ReportItemMetaPaintText(out, this);
				mt->sqlId = sql_id;
				//--mt->editGrants = elementAttribute("editGrants");
			}
			//qfInfo() << "creating item:" << mt;
			mt->pen = style.pen();
			mt->font = style.font();
			mt->text = text.mid(0, m_indexToPrint - initial_index_to_print);
			//qfWarning() << "text:" << text;
			mt->textOption = text_option;
			mt->renderedRect = rendered_bounding_rect;
			mt->renderedRect.flags = designedRect.flags;
		}
		//qfDebug().color(QFLog::Green, QFLog::Red) << "\tleading:" << processor()->fontMetrics(style.font).leading() << "\theight:" << processor()->fontMetrics(style.font).height();
		qfDebug() << "\tchild rendered rect:" << rendered_bounding_rect.toString();
	}
	qfDebug() << "\t<<< CHILDREN paraText return:" << res.toString();
	return res;
}
Ejemplo n.º 4
0
/*
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;
}