int main( int argc, char** argv ) { QApplication app( argc, argv ); KDReports::Report report; report.setHeaderBodySpacing( 10 ); // mm report.setFooterBodySpacing( 10 ); // mm // report.setWatermarkPixmap( QPixmap( ":/kdab.jpg" ) ); // report.setWatermarkText( QString::null ); KDReports::Header& header = report.header( KDReports::OddPages ); QPixmap kdab( ":/kdab_small.jpg" ); // add a border around the pixmap, mostly for debugging //QPainter painter( &kdab ); //painter.drawRect( 0, 0, kdab.width() - 1, kdab.height() - 1 ); KDReports::ImageElement imageElement( kdab ); // The image size can be set in mm or in percent of the page width (without margins) // imageElement.setWidth( 50 ); // mm imageElement.setWidth( 40, KDReports::Percent ); header.addElement( imageElement ); header.addVariable( KDReports::PageNumber ); header.addInlineElement( KDReports::TextElement( " / " ) ); header.addVariable( KDReports::PageCount ); header.addInlineElement( KDReports::TextElement( ", Date: " ) ); header.addVariable( KDReports::TextDate ); header.addInlineElement( KDReports::TextElement( ", Time: " ) ); header.addVariable( KDReports::TextTime ); KDReports::Header& evenPagesHeader = report.header( KDReports::EvenPages ); evenPagesHeader.addElement( imageElement ); evenPagesHeader.addInlineElement( KDReports::TextElement( "Even pages header: " ) ); evenPagesHeader.addVariable( KDReports::PageNumber ); evenPagesHeader.addInlineElement( KDReports::TextElement( " / " ) ); evenPagesHeader.addVariable( KDReports::PageCount ); KDReports::Footer& footer = report.footer(); KDReports::TextElement companyAddressElement( QString::fromUtf8( "Klarälvdalens Datakonsult AB\nRysktorp\nSE-68392 Hagfors\nSweden" ) ); footer.addElement( companyAddressElement, Qt::AlignRight ); KDReports::TextElement titleElement; titleElement << "Price list example"; titleElement.setPointSize( 18 ); report.addElement( titleElement, Qt::AlignHCenter ); report.addVerticalSpacing( 10 ); // 1 cm const QColor titleElementColor( 204, 204, 255 ); // A text element with the title above a table // Note that the background color is not just behind the text (as setBackground() would do), // but behind the whole paragraph, up until the right margin of the page. KDReports::TextElement tableTitleElement( "Network Peripherals" ); tableTitleElement.setBold( true ); report.addElement( tableTitleElement, Qt::AlignLeft, titleElementColor ); TableModel table1; table1.setDataHasVerticalHeaders( false ); table1.loadFromCSV( ":/table1" ); // Q_ASSERT( table1.headerData( 0, Qt::Vertical ).toString() == "10/100 Mbps switch" ); //Q_ASSERT( table1.data( table1.index( 0, 0 ) ).toString() == "Product" ); KDReports::AutoTableElement autoTableElement1( &table1 ); autoTableElement1.setWidth( 100, KDReports::Percent ); report.addElement( autoTableElement1 ); report.addVerticalSpacing( 5 ); // Notice how elements can be copied and modified // This way, we use the same font attributes for all title elements KDReports::TextElement tableTitleElement2 = tableTitleElement; tableTitleElement2.setText( "Printer Cartridges" ); report.addElement( tableTitleElement2, Qt::AlignLeft, titleElementColor ); TableModel table2; table2.setDataHasVerticalHeaders( false ); table2.loadFromCSV( ":/table2" ); KDReports::AutoTableElement autoTableElement2( &table2 ); autoTableElement2.setWidth( 100, KDReports::Percent ); report.addElement( autoTableElement2 ); // and again, on the second page report.addPageBreak(); report.addElement( tableTitleElement, Qt::AlignLeft, titleElementColor ); report.addElement( autoTableElement1 ); report.addVerticalSpacing( 5 ); report.addElement( tableTitleElement2, Qt::AlignLeft, titleElementColor ); report.addElement( autoTableElement2 ); report.addVerticalSpacing( 5 ); // =========================================================================== // Another kind of table, where the data comes from code and not from a model: // =========================================================================== KDReports::TableElement tableElement; tableElement.setHeaderRowCount( 2 ); tableElement.setPadding( 3 ); QColor headerColor( "#DADADA" ); // Merged header in row 0 KDReports::Cell& topHeader = tableElement.cell( 0, 0 ); topHeader.setColumnSpan( 2 ); topHeader.setBackground( headerColor ); topHeader.addElement( KDReports::TextElement( "TableElement example" ), Qt::AlignHCenter ); // Normal header in row 1 KDReports::Cell& headerCell1 = tableElement.cell( 1, 0 ); headerCell1.setBackground( headerColor ); // This would look better if centered vertically. This feature is only available since // Qt-4.3 though (QTextCharFormat::AlignMiddle) QPixmap systemPixmap( ":/system.png" ); headerCell1.addElement( KDReports::ImageElement( systemPixmap ) ); headerCell1.addInlineElement( KDReports::TextElement( " Item" ) ); KDReports::Cell& headerCell2 = tableElement.cell( 1, 1 ); headerCell2.setBackground( headerColor ); KDReports::TextElement expected( "Expected" ); expected.setItalic( true ); expected.setBackground( QColor("#999999") ); // note that this background only applies to this element headerCell2.addElement( expected ); headerCell2.addInlineElement( KDReports::TextElement( " shipping time" ) ); // Data in rows 2 and 3 tableElement.cell( 2, 0 ).addElement( KDReports::TextElement( "Network Peripherals" ) ); tableElement.cell( 2, 1 ).addElement( KDReports::TextElement( "4 days" ) ); tableElement.cell( 3, 0 ).addElement( KDReports::TextElement( "Printer Cartridges" ) ); tableElement.cell( 3, 1 ).addElement( KDReports::TextElement( "3 days" ) ); report.addElement( tableElement ); KDReports::PreviewDialog preview( &report ); return preview.exec(); }
bool KDReports::XmlParser::processNode( const QDomNode& node, KDReports::ReportBuilder* builder, bool inHeader, bool inFooter ) { // Loop over elements for ( QDomElement element = node.firstChildElement() ; !element.isNull(); element = element.nextSiblingElement() ) { if ( testForErrorAndFillErrorDetails() ) return false; const QString name = element.tagName(); if( name == QLatin1String( "text" ) ) { // Handle <text> element KDReports::TextElement textElement; QString id; const QString text = extractText( element, &id, m_report->d->m_currentModel, m_report->d->m_currentRow ); textElement.setText( text ); textElement.setId( id ); const QColor bgColor = KDReports::XmlHelper::readBackground( element ); if( bgColor.isValid() ) textElement.setBackground( bgColor ); if( element.hasAttribute( QLatin1String( "pointsize" ) ) ) { const int pointSize = element.attribute( QLatin1String( "pointsize" ) ).toInt(); if( pointSize ) textElement.setPointSize( pointSize ); } if( element.hasAttribute( QLatin1String( "color" ) ) ) { const QString name = element.attribute( QLatin1String( "color" ) ); textElement.setTextColor( QColor( name ) ); } if( element.hasAttribute( QLatin1String( "font" ) ) ) { textElement.setFontFamily( element.attribute( QLatin1String( "font" ) ) ); } if( element.hasAttribute( QLatin1String( "bold" ) ) ) { bool bold = false; if( element.attribute( QLatin1String( "bold" ) ) == QLatin1String( "true" ) ) bold = true; textElement.setBold( bold ); } if( element.hasAttribute( QLatin1String( "italic" ) ) ) { bool italic = false; if( element.attribute( QLatin1String( "italic" ) ) == QLatin1String( "true" ) ) italic = true; textElement.setItalic( italic ); } if( element.hasAttribute( QLatin1String( "strikeout" ) ) ) { bool strikeOut = false; if( element.attribute( QLatin1String( "strikeout" ) ) == QLatin1String( "true" ) ) strikeOut = true; textElement.setStrikeOut( strikeOut ); } if( element.hasAttribute( QLatin1String( "underline" ) ) ) { bool underline = false; if( element.attribute( QLatin1String( "underline" ) ) == QLatin1String( "true" ) ) underline = true; textElement.setUnderline( underline ); } const QString oldId = textElement.id(); if ( m_xmlElementHandler && !m_xmlElementHandler->textElement( textElement, element ) ) continue; if ( textElement.id() != oldId ) { // The handler modified the text element's id, look up the value again. const QHash<QString, QString>::const_iterator it = m_textValues.constFind( textElement.id() ); if ( it != m_textValues.constEnd() ) { textElement.setText( *it ); } } if ( !builder ) { error( QObject::tr( "<text> is only supported in WordProcessing mode" ) ); } else { if( element.hasAttribute( QLatin1String( "inline" ) ) ) { builder->addInlineElementPublic( textElement ); } else { Qt::AlignmentFlag alignment = Qt::AlignLeft; if( element.hasAttribute( QLatin1String( "alignment" ) ) ) alignment = KDReports::XmlHelper::stringToAlignment( element.attribute( QLatin1String( "alignment" ) ) ); const QColor bgColor = KDReports::XmlHelper::readColor( element, "paragraph-background" ); builder->addBlockElementPublic( textElement, alignment, bgColor ); } } } else if( name == QLatin1String( "html" ) ) { // Handle <html> element KDReports::HtmlElement htmlElement; QString id; const QString text = extractText( element, &id ); htmlElement.setHtml( text ); htmlElement.setId( id ); QColor bgColor = KDReports::XmlHelper::readBackground( element ); if( bgColor.isValid() ) htmlElement.setBackground( bgColor ); const QString oldId = htmlElement.id(); if ( m_xmlElementHandler && !m_xmlElementHandler->htmlElement( htmlElement, element ) ) continue; if ( htmlElement.id() != oldId ) { // The handler modified the text element's id, look up the value again. const QHash<QString, QString>::const_iterator it = m_textValues.constFind( htmlElement.id() ); if ( it != m_textValues.constEnd() ) { htmlElement.setHtml( *it ); } } addElement( htmlElement, builder, element ); } else if ( name == QLatin1String( "tabs" ) ) { if ( !builder ) { error( QObject::tr( "<tabs> is only supported in WordProcessing mode" ) ); } else { parseTabs( builder, element ); } } else if ( name == QLatin1String( "paragraph-margins" ) ) { if ( !builder ) { error( QObject::tr( "<paragraph-margins> is only supported in WordProcessing mode" ) ); } else { parseParagraphMargins( builder, element ); } } else if( name == QLatin1String( "hr" ) ) { // Handle <hr> element KDReports::HtmlElement htmlElement; htmlElement.setHtml( QString::fromLatin1("<hr>") ); if ( m_xmlElementHandler && !m_xmlElementHandler->htmlElement( htmlElement, element ) ) continue; addElement( htmlElement, builder, element ); } else if( name == QLatin1String( "vspace" ) ) { // Handle <vspace> element if( !element.hasAttribute( QLatin1String( "size" ) ) ) continue; // size attribute is mandatory for VSpace int size = element.attribute( QLatin1String( "size" ) ).toInt(); if ( !builder ) { error( QObject::tr( "<vspace> is only supported in WordProcessing mode" ) ); } else { if( builder != m_report->d->builder() ) { error( QObject::tr("<vspace> not allowed in headers, footers, or table cells") ); return false; } } XmlElementHandlerV2* v2 = dynamic_cast<XmlElementHandlerV2 *>(m_xmlElementHandler); if (v2 && !v2->vspace(size, element)) continue; m_report->addVerticalSpacing( size ); } else if( name == QLatin1String( "table" ) ) { // Handle <table> element const QString model = element.attribute( QLatin1String( "model" ) ); if ( model.isEmpty() ) { if ( !builder ) { error( QObject::tr( "<table> without a model is only supported in WordProcessing mode" ) ); continue; } KDReports::TableElement tableElement; const int headerRowCount = element.attribute( QLatin1String( "headerRowCount" ) ).toInt(); // default 0 tableElement.setHeaderRowCount( headerRowCount ); if ( element.hasAttribute( QLatin1String( "cellpadding" ) ) ) tableElement.setPadding( element.attribute( QLatin1String( "cellpadding" ) ).toInt() ); parseCommonTableAttributes( tableElement, element ); if ( m_xmlElementHandler && !m_xmlElementHandler->startTableElement( tableElement, element ) ) continue; if ( !parseTableContents( tableElement, element, *builder, inHeader, inFooter ) ) return false; if ( m_xmlElementHandler && !m_xmlElementHandler->endTableElement( tableElement, element ) ) continue; addElement( tableElement, builder, element ); } else { KDReports::AutoTableElement tableElement( model ); if( element.attribute( QLatin1String( "verticalHeaderVisible" ) ) == QLatin1String( "false" ) ) tableElement.setVerticalHeaderVisible(false); if( element.attribute( QLatin1String( "horizontalHeaderVisible" ) ) == QLatin1String( "false" ) ) tableElement.setHorizontalHeaderVisible(false); QColor headerBgColor = KDReports::XmlHelper::readColor( element, "header-background" ); if ( headerBgColor.isValid() ) tableElement.setHeaderBackground( headerBgColor ); parseCommonTableAttributes( tableElement, element ); if ( m_xmlElementHandler && !m_xmlElementHandler->autoTableElement( tableElement, element ) ) continue; if ( m_report->reportMode() == Report::SpreadSheet ) { m_report->mainTable()->setAutoTableElement( tableElement ); } else { addElement( tableElement, builder, element ); } } } else if( name == QLatin1String( "chart" ) ) { // Handle <chart> element KDReports::ChartElement chartElement( element.attribute( QLatin1String( "model" ) ) ); QColor bgColor = KDReports::XmlHelper::readBackground( element ); if( bgColor.isValid() ) chartElement.setBackground( bgColor ); int width = 100, height = 100; Unit unit = Millimeters; if( element.hasAttribute( QLatin1String( "width" ) ) ) { QString str = element.attribute( QLatin1String( "width" ) ); if ( str.endsWith( QLatin1Char('%') ) ) { str.chop( 1 ); unit = Percent; } width = str.toInt(); } if( element.hasAttribute( QLatin1String( "height" ) ) ) { QString str = element.attribute( QLatin1String( "height" ) ); if ( str.endsWith( QLatin1Char('%') ) ) { str.chop( 1 ); unit = Percent; } height = str.toInt(); } chartElement.setSize( width, height, unit ); if ( m_xmlElementHandler && !m_xmlElementHandler->chartElement( chartElement, element ) ) continue; addElement( chartElement, builder, element ); } else if( name == QLatin1String( "image" ) ) { // Handle <image> element QString id; QImage image = extractImage( element, &id ); KDReports::ImageElement imageElement( image ); imageElement.setId(id); if( element.hasAttribute( QLatin1String( "width" ) ) ) { QString widthStr = element.attribute( QLatin1String( "width" ) ); if ( widthStr.endsWith( QLatin1Char('%') ) ) { widthStr.truncate( widthStr.length() - 1 ); imageElement.setWidth( widthStr.toInt(), KDReports::Percent ); } else { imageElement.setWidth( widthStr.toInt() ); } } else if( element.hasAttribute( QLatin1String( "height" ) ) ) { // mutually exclusive with "width"! QString heightStr = element.attribute( QLatin1String( "height" ) ); if ( heightStr.endsWith( QLatin1Char('%') ) ) { heightStr.truncate( heightStr.length() - 1 ); imageElement.setHeight( heightStr.toInt(), KDReports::Percent ); } else { imageElement.setHeight( heightStr.toInt() ); } } else if ( element.hasAttribute( QLatin1String( "fitToPage" ) ) ) { imageElement.setFitToPage(); } if ( m_xmlElementHandler && !m_xmlElementHandler->imageElement( imageElement, element ) ) continue; addElement( imageElement, builder, element ); } else if( name == QLatin1String( "header" ) ) { const KDReports::HeaderLocations loc = KDReports::XmlHelper::parseHeaderLocation( element.attribute( QLatin1String( "location" ) ) ); KDReports::Header& header = m_report->header( loc ); parseHeaderFooterAttribute( header, element ); if ( m_xmlElementHandler && !m_xmlElementHandler->startHeader( header, element ) ) continue; if( !processNode( element, &header.d->m_builder, true, false ) ) return false; if ( m_xmlElementHandler ) m_xmlElementHandler->endHeader( header, element ); } else if( name == QLatin1String( "footer" ) ) { const KDReports::HeaderLocations loc = KDReports::XmlHelper::parseHeaderLocation( element.attribute( QLatin1String( "location" ) ) ); KDReports::Footer& footer = m_report->footer( loc ); parseHeaderFooterAttribute( footer, element ); if ( m_xmlElementHandler && !m_xmlElementHandler->startFooter( footer, element ) ) continue; if( !processNode( element, &footer.d->m_builder, false, true ) ) return false; if ( m_xmlElementHandler ) m_xmlElementHandler->endFooter( footer, element ); } else if( name == QLatin1String( "variable" ) ) { if( !inHeader && !inFooter ) { error( QObject::tr("<variable> tags only allowed in headers and footers") ); return false; } if( !element.hasAttribute( QLatin1String( "type" ) ) ) { error( QObject::tr("<variable> tags must have a 'type' attribute") ); return false; } Q_ASSERT( builder ); if ( builder ) { const QString type = element.attribute( QLatin1String( "type" ) ); KDReports::VariableType vt = KDReports::XmlHelper::stringToVariableType( type ); XmlElementHandlerV2* v2 = dynamic_cast<XmlElementHandlerV2 *>(m_xmlElementHandler); if (v2 && !v2->variable(vt, element)) continue; builder->addVariablePublic( vt ); } } else if ( name == QLatin1String( "page-break" ) ) { if ( m_xmlElementHandler && !m_xmlElementHandler->pageBreak( element ) ) continue; m_report->addPageBreak(); } else if ( name == QLatin1String( "ifdef" ) ) { if ( element.hasAttribute( QLatin1String( "id" ) ) ) { const QString id = element.attribute( QLatin1String( "id" ) ); const bool skip = m_textValues.value( id ).isEmpty(); if( !skip ) { if ( !processNode( element, builder, inHeader, inFooter ) ) return false; } } } else if ( name == QLatin1String( "custom" ) ) { if ( m_xmlElementHandler ) m_xmlElementHandler->customElement( element ); } else if ( name == QLatin1String( "hline" ) ) { KDReports::HLineElement hLineElement; if ( element.hasAttribute( QLatin1String( "thickness" ) ) ) { const double thickness = element.attribute( QLatin1String( "thickness" ) ).toDouble(); hLineElement.setThickness( thickness ); } if ( element.hasAttribute( QLatin1String( "color" ) ) ) { const QColor color = KDReports::XmlHelper::readColor( element, "color" ); hLineElement.setColor( color ); } if ( element.hasAttribute( QLatin1String( "margin" ) ) ) { const int margin = element.attribute( QLatin1String( "margin" ) ).toInt(); hLineElement.setMargin( margin ); } #ifdef KDREPORTS_ALLOW_BINARY_INCOMPATIBILITY if ( m_xmlElementHandler && !m_xmlElementHandler->hLineElement( hLineElement, element ) ) continue; #else XmlElementHandlerV2* v2 = dynamic_cast<XmlElementHandlerV2 *>(m_xmlElementHandler); if (v2 && !v2->hLineElement(hLineElement, element)) continue; #endif addElement( hLineElement, builder, element ); } else { error( QObject::tr( "KDReports::Report::loadFromXML(): Unknown element %1" ).arg( name ) ); } } if ( testForErrorAndFillErrorDetails() ) return false; return true; }
void ReportView::generate() { // Check if there are rows in model. If so, generate report if(m_tableModel->rowCount() > 0) { // Create report container KDReports::Report report; // Generate table element using the table model KDReports::AutoTableElement tableElement(m_tableModel); // Show vertical header tableElement.setVerticalHeaderVisible(true); // Title text KDReports::TextElement title; title.setText("Transaction Report"); // Show in bold format title.setBold(true); // Underline text title.setUnderline(true); // Set font size to 20 title.setPointSize(20); // Add title to report report.addElement(title); // Insert vertical spacing for easier reading report.addVerticalSpacing(2); // Text to display report date KDReports::TextElement date; // Insert to date date << "Date: " << m_genData.fromDate.toString(); // Check if report is not daily if(!m_genData.daily) // Add to date date << " - " << m_genData.toDate.toString(); // Insert date element in to report report.addElement(date); // Insert 10 mm vertical spacing report.addVerticalSpacing(10); // Insert table element report.addElement(tableElement); // Insert a further 10 mm vertical spacing report.addVerticalSpacing(10); // Get report sums ReportTable::Sums sums = static_cast<ReportTable*>(m_tableModel) ->GetSums(m_genData); // Check validity of data if(sums.cost == -1) { // Data invalid, notify user QMessageBox::critical(this, "Failed to generate report.", "Report data is invalid.", QMessageBox::Ok); // Exit function return; } // Total revenue text KDReports::TextElement revenueTotal; // insert total revenue values revenueTotal << "Total revenue: " // convert to localized currency format << QLocale::system().toCurrencyString(sums.revenue); // total cost text KDReports::TextElement costTotal; costTotal << "Total cost: " // convert to localized currency format << QLocale::system().toCurrencyString(sums.cost); // total profit text KDReports::TextElement profitTotal; profitTotal << "Total profit: " // convert to localized currency format << QLocale::system().toCurrencyString(sums.profit); // Add revenue total to report report.addElement(revenueTotal); // Add cost total to report report.addElement(costTotal); // Add profit total to report report.addElement(profitTotal); // Create preview dialog using report. KDReports::PreviewDialog preview(&report); // Show preview dialog preview.exec(); } else // No data in table model { // Notify user of error QMessageBox::warning(this, "No report generated.", "Please generate a report before attempting to print it.", QMessageBox::Ok); } }