File indexing completed on 2024-05-05 04:43:21
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com) 0003 * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Lesser General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2.1 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Lesser General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Lesser General Public 0016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 0017 */ 0018 0019 #include "KReportHTMLCSSRenderer_p.h" 0020 #include "KReportRenderObjects.h" 0021 #include "kreport_debug.h" 0022 0023 #include <QTemporaryFile> 0024 #include <QDir> 0025 #include <QPainter> 0026 #include <QString> 0027 0028 namespace KReportPrivate { 0029 0030 HTMLCSSRenderer::HTMLCSSRenderer() 0031 { 0032 0033 } 0034 0035 HTMLCSSRenderer::~HTMLCSSRenderer() 0036 { 0037 0038 } 0039 0040 bool HTMLCSSRenderer::render(const KReportRendererContext& context, ORODocument *document, int page) 0041 { 0042 Q_UNUSED(page); 0043 QTemporaryFile tempHtmlFile; // auto removed by default on destruction 0044 if (!tempHtmlFile.open()) { 0045 kreportWarning() << "Couldn't create temporary file to write into"; 0046 return false; 0047 } 0048 0049 QTextStream out(&tempHtmlFile); 0050 0051 QString dirSuffix = QLatin1String(".files"); 0052 QDir tempDir; 0053 QFileInfo fi(tempHtmlFile); 0054 0055 QString tempFileName = fi.absoluteFilePath(); 0056 m_tempDirName = tempFileName + dirSuffix; 0057 m_actualDirName = context.url().fileName() + dirSuffix; 0058 0059 if (!tempDir.mkpath(m_tempDirName)) 0060 return false; 0061 0062 out << renderCSS(document); 0063 0064 out.flush(); 0065 tempHtmlFile.close(); 0066 0067 bool status = true; //!< @todo KIO 0068 // if (KIO::NetAccess::upload(tempFileName, context.destinationUrl, 0) && KIO::NetAccess::dircopy(QUrl(m_tempDirName), QUrl(context.destinationUrl.url() + dirSuffix), 0)) { 0069 // status = true; 0070 // } 0071 0072 // cleanup the temporary directory 0073 tempDir.setPath(m_tempDirName); 0074 QStringList fileList = tempDir.entryList(); 0075 foreach(const QString& fileName, fileList) { 0076 tempDir.remove(fileName); 0077 } 0078 tempDir.rmdir(m_tempDirName); 0079 0080 return status; 0081 } 0082 0083 //! @todo use QTextStream for efficiency 0084 QString HTMLCSSRenderer::renderCSS(ORODocument *document) 0085 { 0086 QString html; 0087 QString body; 0088 QString style; 0089 QStringList styles; 0090 int styleindex; 0091 bool renderedPageHead = false; 0092 bool renderedPageFoot = false; 0093 0094 QDir d(m_tempDirName); 0095 // Render Each Section 0096 for (int s = 0; s < document->sectionCount(); s++) { 0097 OROSection *section = document->section(s); 0098 0099 if (section->type() == KReportSectionData::Type::GroupHeader 0100 || section->type() == KReportSectionData::Type::GroupFooter 0101 || section->type() == KReportSectionData::Type::Detail 0102 || section->type() == KReportSectionData::Type::ReportHeader 0103 || section->type() == KReportSectionData::Type::ReportFooter 0104 || (section->type() == KReportSectionData::Type::PageHeaderAny && !renderedPageHead) 0105 || (section->type() == KReportSectionData::Type::PageFooterAny && !renderedPageFoot 0106 && s > document->sectionCount() - 2)) 0107 { // render the page foot right at the end, it 0108 // will either be the last or second last 0109 // section if there is a report footer 0110 if (section->type() == KReportSectionData::Type::PageHeaderAny) 0111 renderedPageHead = true; 0112 0113 if (section->type() == KReportSectionData::Type::PageFooterAny) 0114 renderedPageFoot = true; 0115 0116 style = QLatin1String("position: relative; top: 0pt; left: 0pt; background-color: ") + section->backgroundColor().name() + QLatin1String("; height: ") + QString::number(section->height()) + QLatin1String("pt;"); 0117 0118 if (!styles.contains(style)) { 0119 styles << style; 0120 } 0121 styleindex = styles.indexOf(style); 0122 0123 body += QLatin1String("<div class=\"style") + QString::number(styleindex) + QLatin1String("\">\n"); 0124 //Render the objects in each section 0125 for (int i = 0; i < section->primitiveCount(); i++) { 0126 OROPrimitive * prim = section->primitive(i); 0127 //kreportDebug() << "Got object type" << prim->type(); 0128 if (OROTextBox *tb = dynamic_cast<OROTextBox*>(prim)) { 0129 QColor bg = tb->textStyle().backgroundColor; 0130 style = QLatin1String("position: absolute; ") + 0131 QLatin1String("background-color: ") + QString::fromLatin1("rgba(%1,%2,%3,%4)") 0132 .arg(bg.red()) 0133 .arg(bg.green()) 0134 .arg(bg.blue()) 0135 .arg(0.01 * tb->textStyle().backgroundOpacity) +QLatin1String( "; ") + 0136 QLatin1String("top: ") + QString::number(tb->position().y()) + QLatin1String("pt; ") + 0137 QLatin1String("left: ") + QString::number(tb->position().x()) + QLatin1String("pt; ") + 0138 QLatin1String("font-size: ") + QString::number(tb->textStyle().font.pointSize()) + QLatin1String("pt; ") + 0139 QLatin1String("color: ") + tb->textStyle().foregroundColor.name() + QLatin1String("; ") + 0140 QLatin1String("width: ") + QString::number(tb->size().width()) + QLatin1String("px;") + 0141 QLatin1String("height: ") + QString::number(tb->size().height()) + QLatin1String("px;") ; 0142 //! @todo opaque text + translucent background 0143 //it looks a pain to implement 0144 //http://developer.mozilla.org/en/docs/Useful_CSS_tips:Color_and_Background 0145 //style += "filter:alpha(opacity=" + QString::number((tb->textStyle().bgOpacity / 255) * 100) + ");"; //ie opacity 0146 //style += "opacity: " + QString::number(tb->textStyle().bgOpacity / 255.0) + ";"; 0147 0148 if (!styles.contains(style)) { 0149 styles << style; 0150 } 0151 styleindex = styles.indexOf(style); 0152 0153 body += QLatin1String("<div class=\"style") + QString::number(styleindex) + QLatin1String("\">") + 0154 tb->text() + 0155 QLatin1String("</div>\n"); 0156 } else if (OROImage *im = dynamic_cast<OROImage*>(prim)) { 0157 style = QLatin1String("position: absolute; ") + 0158 QLatin1String("top: ") + QString::number(im->position().y()) + QLatin1String("pt; ") + 0159 QLatin1String("left: ") + QString::number(im->position().x()) + QLatin1String("pt; "); 0160 if (!styles.contains(style)) { 0161 styles << style; 0162 } 0163 styleindex = styles.indexOf(style); 0164 0165 body += QLatin1String("<div class=\"style") + QString::number(styleindex) + QLatin1String("\">") + 0166 QLatin1String("<img width=\"") + QString::number(im->size().width()) + QLatin1String("px") + QLatin1String("\" height=\"") + QString::number(im->size().height()) + QLatin1String("px") + QLatin1String("\" src=\"./") + m_actualDirName + QLatin1String("/object") + QString::number(s) + QString::number(i) + QLatin1String(".png\"></img>") + 0167 QLatin1String("</div>\n"); 0168 0169 0170 im->image().save(m_tempDirName + QLatin1String("/object") + QString::number(s) + QString::number(i) + QLatin1String(".png")); 0171 } else if (OROPicture *im = dynamic_cast<OROPicture*>(prim)) { 0172 style = QLatin1String("position: absolute; ") + 0173 QLatin1String("top: ") + QString::number(im->position().y()) + QLatin1String("pt; ") + 0174 QLatin1String("left: ") + QString::number(im->position().x()) + QLatin1String("pt; "); 0175 if (!styles.contains(style)) { 0176 styles << style; 0177 } 0178 styleindex = styles.indexOf(style); 0179 0180 body += QLatin1String("<div class=\"style") + QString::number(styleindex) + QLatin1String("\">") + 0181 QLatin1String("<img width=\"") + QString::number(im->size().width()) + QLatin1String("px") + QLatin1String("\" height=\"") + QString::number(im->size().height()) + QLatin1String("px") + QLatin1String("\" src=\"./") + m_actualDirName + QLatin1String("/object") + QString::number(s) + QString::number(i) + QLatin1String(".png\"></img>") + 0182 QLatin1String("</div>\n"); 0183 0184 QImage image(im->size().toSize(), QImage::Format_RGB32); 0185 QPainter painter(&image); 0186 im->picture()->play(&painter); 0187 image.save(m_tempDirName + QLatin1String("/object") + QString::number(s) + QString::number(i) + QLatin1String(".png")); 0188 } else { 0189 kreportWarning() << "unrecognized primitive type"; 0190 } 0191 } 0192 body += QLatin1String("</div>\n"); 0193 } 0194 } 0195 0196 //! @todo add option for creating separate css file 0197 html = QLatin1String("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" 0198 "<html>\n" 0199 "<head>\n" 0200 "<style type=\"text/css\">\n"); 0201 0202 for (int i = 0; i < styles.count(); ++i) { 0203 html += QLatin1String(".style") + QString::number(i) + QLatin1String("{") + styles[i] + QLatin1String("}\n"); 0204 } 0205 0206 html += QLatin1String("</style>\n") + 0207 QLatin1String("<title>") + document->title() + QLatin1String("</title>\n") + 0208 QLatin1String("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n") + 0209 QLatin1String("<meta name=\"generator\" content=\"Kexi\">\n") + 0210 QLatin1String("</head>\n") + 0211 QLatin1String("<body>\n") + 0212 body + 0213 QLatin1String("\n</body>\n") + 0214 QLatin1String("</html>\n"); 0215 0216 return html; 0217 } 0218 0219 }