00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qstring.h>
00022 #include <qtextcodec.h>
00023 #include <qfile.h>
00024 #include <qfileinfo.h>
00025 #include <qdir.h>
00026 #include <qpicture.h>
00027
00028 #include <klocale.h>
00029 #include <kdebug.h>
00030
00031 #include <KWEFUtil.h>
00032 #include <KWEFBaseWorker.h>
00033
00034 #include "ExportFilter.h"
00035
00036 QString HtmlWorker::escapeHtmlText(const QString& strText) const
00037 {
00038
00039
00040 return KWEFUtil::EscapeSgmlText(getCodec(),strText,true,false);
00041 }
00042
00043 bool HtmlWorker::makeTable(const FrameAnchor& anchor)
00044 {
00045 *m_streamOut << "<table>\n";
00046 *m_streamOut << "<tbody>\n";
00047
00048 QValueList<TableCell>::ConstIterator itCell;
00049
00050 int rowCurrent=0;
00051 *m_streamOut << "<tr>\n";
00052
00053
00054 for (itCell=anchor.table.cellList.begin();
00055 itCell!=anchor.table.cellList.end(); itCell++)
00056 {
00057 if (rowCurrent!=(*itCell).row)
00058 {
00059 rowCurrent=(*itCell).row;
00060 *m_streamOut << "</tr>\n<tr>\n";
00061 }
00062
00063 *m_streamOut << "<td";
00064 if ( (*itCell).m_rows > 1 )
00065 *m_streamOut << " rowspan=\"" << (*itCell).m_rows << "\"";
00066 if ( (*itCell).m_cols > 1 )
00067 *m_streamOut << " colspan=\"" << (*itCell).m_cols << "\"";
00068 *m_streamOut << ">\n";
00069
00070 if (!doFullAllParagraphs(*(*itCell).paraList))
00071 {
00072 return false;
00073 }
00074
00075 *m_streamOut << "</td>\n";
00076 }
00077
00078 *m_streamOut << "</tr>\n";
00079 *m_streamOut << "</tbody>\n";
00080 *m_streamOut << "</table>\n";
00081
00082 return true;
00083 }
00084
00085 QString HtmlWorker::getAdditionalFileName(const QString& additionalName)
00086 {
00087 kdDebug(30503) << "HtmlWorker::getAdditionalFileName " << additionalName << endl;
00088
00089 QDir dir(m_strFileDir);
00090 kdDebug(30503) << "Base directory: " << m_strFileDir << endl;
00091
00092 if (!dir.exists(m_strSubDirectoryName))
00093 {
00094
00095 kdDebug(30503) << "Creating directory: " << m_strSubDirectoryName << endl;
00096 dir.mkdir(m_strSubDirectoryName);
00097 }
00098
00099 QString strFileName(m_strSubDirectoryName);
00100 strFileName+="/";
00101 const int result=additionalName.findRev("/");
00102 if (result>=0)
00103 {
00104 strFileName+=additionalName.mid(result+1);
00105 }
00106 else
00107 {
00108 strFileName+=additionalName;
00109 }
00110
00111
00112
00113 QString strBackupName(strFileName);
00114 strBackupName+="~";
00115 kdDebug(30503) << "Remove backup file: " << strBackupName << endl;
00116
00117 dir.remove(strBackupName);
00118 kdDebug(30503) << "Moving file: " << additionalName << " => " << strBackupName << endl;
00119 dir.rename(strFileName,strBackupName);
00120
00121 return strFileName;
00122 }
00123
00124 bool HtmlWorker::makeImage(const FrameAnchor& anchor)
00125 {
00126 const QString strImageName(getAdditionalFileName(anchor.picture.koStoreName));
00127
00128 QString strImagePath(m_strFileDir);
00129 strImagePath+='/';
00130 strImagePath+=strImageName;
00131
00132 QByteArray image;
00133
00134 kdDebug(30503) << "Image " << anchor.picture.koStoreName << " will be written in " << strImageName << endl;
00135
00136 if (loadSubFile(anchor.picture.koStoreName,image))
00137 {
00138 bool writePicture = false;
00139
00140 const double height = anchor.frame.bottom - anchor.frame.top;
00141 const double width = anchor.frame.right - anchor.frame.left;
00142
00143 const int pos = anchor.picture.koStoreName.findRev( '.' );
00144 QString extension;
00145 if ( pos > -1 )
00146 extension = anchor.picture.koStoreName.mid( pos+1 ).lower();
00147
00148 if ( extension == "png" || extension == "jpeg" || extension == "jpg" || extension == "gif"
00149 || extension == "bmp" )
00150 {
00151 *m_streamOut << "<img ";
00152 *m_streamOut << "src=\"" << escapeHtmlText(strImageName) << "\" ";
00153 *m_streamOut << "alt=\"" << escapeHtmlText(anchor.picture.key.filename()) << "\"";
00154 *m_streamOut << (isXML()?"/>":">");
00155 writePicture = true;
00156 }
00157 else if ( extension == "svg" )
00158 {
00159
00160 *m_streamOut << "<object data=\"" << escapeHtmlText(strImageName) << "\"";
00161 *m_streamOut << " type=\"image/svg+xml\"";
00162 *m_streamOut << " height=\"" << height << "\" width=\"" << width << "\">\n";
00163 *m_streamOut << "</object>";
00164 writePicture = true;
00165 }
00166 else if ( extension == "qpic" )
00167 {
00168
00169 QPicture picture;
00170
00171 QIODevice* io=getSubFileDevice(anchor.picture.koStoreName);
00172 if (!io)
00173 {
00174
00175 return false;
00176 }
00177
00178
00179 if (picture.load(io))
00180 {
00181
00182
00183 *m_streamOut << "<object data=\"" << escapeHtmlText(strImageName) << "\"";
00184 *m_streamOut << " type=\"image/svg+xml\"";
00185 *m_streamOut << " height=\"" << height << "\" width=\"" << width << "\">\n";
00186 *m_streamOut << "</object>";
00187
00188
00189 kdDebug(30506) << "Trying to save clipart to " << strImageName << endl;
00190 if (!picture.save(strImagePath,"svg"))
00191 {
00192 kdError(30506) << "Could not save clipart: " << anchor.picture.koStoreName
00193 << " to " << strImageName << endl;
00194 return false;
00195 }
00196
00197 }
00198 }
00199 else
00200 {
00201
00202 image.resize( 0 );
00203 if ( ! loadAndConvertToImage( anchor.picture.koStoreName, extension, "PNG", image ) )
00204 {
00205 kdWarning(30503) << "Could not convert picture to PNG!" << endl;
00206 return false;
00207 }
00208 *m_streamOut << "<img ";
00209 *m_streamOut << "src=\"" << escapeHtmlText(strImageName) << "\" ";
00210 *m_streamOut << "alt=\"" << escapeHtmlText(anchor.picture.key.filename()) << "\"";
00211 *m_streamOut << (isXML()?"/>":">");
00212 writePicture = true;
00213 }
00214
00215
00216 if ( writePicture )
00217 {
00218 QFile file(strImagePath);
00219
00220 if ( !file.open (IO_WriteOnly) )
00221 {
00222 kdError(30503) << "Unable to open image output file!" << endl;
00223 return false;
00224 }
00225
00226 file.writeBlock(image);
00227 file.close();
00228 }
00229 }
00230 else
00231 {
00232 kdWarning(30503) << "Unable to load picture " << anchor.picture.koStoreName << endl;
00233 }
00234
00235 return true;
00236 }
00237
00238 void HtmlWorker::formatTextParagraph(const QString& strText,
00239 const FormatData& formatOrigin, const FormatData& format)
00240 {
00241 QString strEscaped(escapeHtmlText(strText));
00242
00243
00244 int pos;
00245 QString strBr(isXML()?QString("<br />"):QString("<br>"));
00246 while ((pos=strEscaped.find(QChar(10)))>-1)
00247 {
00248 strEscaped.replace(pos,1,strBr);
00249 }
00250
00251 if (!format.text.missing)
00252 {
00253
00254 openSpan(formatOrigin,format);
00255 }
00256
00257
00258
00259
00260 if (strText==" ")
00261 {
00262 *m_streamOut << " ";
00263
00264 }
00265 else
00266 {
00267 *m_streamOut << strEscaped;
00268 }
00269
00270 if (!format.text.missing)
00271 {
00272
00273 closeSpan(formatOrigin,format);
00274 }
00275 }
00276
00277 void HtmlWorker::ProcessParagraphData (const QString& strTag, const QString ¶Text,
00278 const LayoutData& layout, const ValueListFormatData ¶FormatDataList)
00279 {
00280 if (paraText.isEmpty() && paraFormatDataList.first().id != 6)
00281 {
00282 openParagraph(strTag,layout);
00283 *m_streamOut << " " ;
00284 closeParagraph(strTag,layout);
00285 }
00286 else
00287 {
00288 bool paragraphNotOpened=true;
00289
00290 ValueListFormatData::ConstIterator paraFormatDataIt;
00291
00292 QString partialText;
00293
00294 for ( paraFormatDataIt = paraFormatDataList.begin ();
00295 paraFormatDataIt != paraFormatDataList.end ();
00296 paraFormatDataIt++ )
00297 {
00298 if (1==(*paraFormatDataIt).id)
00299 {
00300
00301 partialText=paraText.mid ( (*paraFormatDataIt).pos, (*paraFormatDataIt).len );
00302
00303 if (paragraphNotOpened)
00304 {
00305 openParagraph(strTag,layout,partialText.ref(0).direction());
00306 paragraphNotOpened=false;
00307 }
00308 formatTextParagraph(partialText,layout.formatData,*paraFormatDataIt);
00309 }
00310 else if (4==(*paraFormatDataIt).id)
00311 {
00312
00313 if (paragraphNotOpened)
00314 {
00315 openParagraph(strTag,layout);
00316 paragraphNotOpened=false;
00317 }
00318 if (9==(*paraFormatDataIt).variable.m_type)
00319 {
00320
00321 *m_streamOut << "<a href=\""
00322 << escapeHtmlText((*paraFormatDataIt).variable.getHrefName())
00323 << "\">"
00324 << escapeHtmlText((*paraFormatDataIt).variable.getLinkName())
00325 << "</a>";
00326 }
00327 else
00328 {
00329
00330 *m_streamOut << escapeHtmlText((*paraFormatDataIt).variable.m_text);
00331 }
00332 }
00333 else if (6==(*paraFormatDataIt).id)
00334 {
00335
00336
00337 if (6==(*paraFormatDataIt).frameAnchor.type)
00338 {
00339
00340
00341 if (!paragraphNotOpened)
00342 {
00343
00344 closeParagraph(strTag,layout);
00345 }
00346 makeTable((*paraFormatDataIt).frameAnchor);
00347
00348 paragraphNotOpened=true;
00349
00350 }
00351
00352 else if ( ( 2 == (*paraFormatDataIt).frameAnchor.type )
00353 || ( 5 == (*paraFormatDataIt).frameAnchor.type ) )
00354 {
00355
00356 if (paragraphNotOpened)
00357 {
00358 openParagraph( strTag, layout,partialText.ref(0). direction() );
00359 paragraphNotOpened=false;
00360 }
00361 makeImage((*paraFormatDataIt).frameAnchor);
00362 }
00363 else
00364 {
00365 kdWarning(30503) << "Unknown anchor type: "
00366 << (*paraFormatDataIt).frameAnchor.type << endl;
00367 }
00368 }
00369 }
00370 if (!paragraphNotOpened)
00371 {
00372
00373 closeParagraph(strTag,layout);
00374 }
00375 }
00376 }
00377
00378 bool HtmlWorker::doFullParagraph(const QString& paraText,
00379 const LayoutData& layout, const ValueListFormatData& paraFormatDataList)
00380 {
00381 kdDebug(30503) << "Entering HtmlWorker::doFullParagraph" << endl << paraText << endl;
00382 QString strParaText=paraText;
00383 QString strTag;
00384
00385 if ( layout.counter.numbering == CounterData::NUM_LIST )
00386 {
00387 const uint layoutDepth=layout.counter.depth+1;
00388 const uint listDepth=m_listStack.size();
00389
00390 if (layoutDepth>listDepth)
00391 {
00392 ListInfo newList;
00393 newList.m_typeList=layout.counter.style;
00394 for (uint i=listDepth; i<layoutDepth; i++)
00395 {
00396 *m_streamOut << getStartOfListOpeningTag(layout.counter.style,newList.m_orderedList);
00397 m_listStack.push(newList);
00398 }
00399 }
00400 else if (layoutDepth<listDepth)
00401 {
00402 for (uint i=listDepth; i>layoutDepth; i--)
00403 {
00404 ListInfo oldList=m_listStack.pop();
00405 if (oldList.m_orderedList)
00406 {
00407 *m_streamOut << "</ol>\n";
00408 }
00409 else
00410 {
00411 *m_streamOut << "</ul>\n";
00412 }
00413 }
00414 }
00415
00416
00417 if ( layout.counter.style!=m_listStack.top().m_typeList)
00418 {
00419
00420 ListInfo oldList=m_listStack.pop();
00421 if (oldList.m_orderedList)
00422 {
00423 *m_streamOut << "</ol>\n";
00424 }
00425 else
00426 {
00427 *m_streamOut << "</ul>\n";
00428 }
00429 ListInfo newList;
00430 *m_streamOut << getStartOfListOpeningTag(layout.counter.style,newList.m_orderedList);
00431 newList.m_typeList=layout.counter.style;
00432 m_listStack.push(newList);
00433 }
00434
00435
00436 strTag="li";
00437 }
00438 else
00439 {
00440
00441 if (!m_listStack.isEmpty())
00442 {
00443 for (uint i=m_listStack.size(); i>0; i--)
00444 {
00445 ListInfo oldList=m_listStack.pop();
00446 if (oldList.m_orderedList)
00447 {
00448 *m_streamOut << "</ol>\n";
00449 }
00450 else
00451 {
00452 *m_streamOut << "</ul>\n";
00453 }
00454 }
00455 }
00456 if ( (layout.counter.numbering == CounterData::NUM_CHAPTER)
00457 && (layout.counter.depth<6) )
00458 {
00459 strTag=QString("h%1").arg(layout.counter.depth + 1);
00460 }
00461 else
00462 {
00463 strTag="p";
00464 }
00465 }
00466
00467 ProcessParagraphData(strTag, strParaText, layout, paraFormatDataList);
00468
00469 kdDebug(30503) << "Quiting HtmlWorker::doFullParagraph" << endl;
00470 return true;
00471 }
00472
00473 bool HtmlWorker::doOpenFile(const QString& filenameOut, const QString& )
00474 {
00475 m_ioDevice=new QFile(filenameOut);
00476
00477 if (!m_ioDevice)
00478 {
00479 kdError(30503) << "No output file! Aborting!" << endl;
00480 return false;
00481 }
00482
00483 if ( !m_ioDevice->open (IO_WriteOnly) )
00484 {
00485 kdError(30503) << "Unable to open output file!" << endl;
00486 return false;
00487 }
00488
00489 m_streamOut=new QTextStream(m_ioDevice);
00490
00491 if (!getCodec())
00492 {
00493 kdError(30503) << "Could not create QTextCodec! Aborting" << endl;
00494 return false;
00495 }
00496
00497 kdDebug(30503) << "Charset used: " << getCodec()->name() << endl;
00498
00499 m_streamOut->setCodec( getCodec() );
00500
00501 m_fileName=filenameOut;
00502 QFileInfo base(m_fileName);
00503 m_strFileDir=base.dirPath();
00504 m_strTitle=base.fileName();
00505 m_strSubDirectoryName=base.fileName();
00506 m_strSubDirectoryName+=".dir";
00507
00508 return true;
00509 }
00510
00511 bool HtmlWorker::doCloseFile(void)
00512 {
00513 kdDebug(30503) << __FILE__ << ":" << __LINE__ << endl;
00514 delete m_streamOut;
00515 m_streamOut=NULL;
00516 if (m_ioDevice)
00517 m_ioDevice->close();
00518 return true;
00519 }
00520
00521 void HtmlWorker::writeDocType(void)
00522 {
00523
00524 *m_streamOut << "<!DOCTYPE ";
00525 if (isXML())
00526 {
00527 *m_streamOut << "html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n";
00528 }
00529 else
00530 {
00531 *m_streamOut << "HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
00532 }
00533 }
00534
00535 bool HtmlWorker::doOpenDocument(void)
00536 {
00537
00538
00539 if (isXML())
00540 {
00541 *m_streamOut << "<?xml version=\"1.0\" encoding=\""
00542 << getCodec()->mimeName() << "\"?>" << endl;
00543 }
00544
00545
00546 writeDocType();
00547
00548
00549 *m_streamOut << "<html";
00550 if (isXML())
00551 {
00552
00553 *m_streamOut << " xmlns=\"http://www.w3.org/1999/xhtml\"";
00554 }
00555 *m_streamOut << ">\n";
00556 return true;
00557 }
00558
00559 bool HtmlWorker::doCloseDocument(void)
00560 {
00561 kdDebug(30503) << __FILE__ << ":" << __LINE__ << endl;
00562 *m_streamOut << "</html>\n";
00563 return true;
00564 }
00565
00566 bool HtmlWorker::doFullDocumentInfo(const KWEFDocumentInfo& docInfo)
00567 {
00568 QString strText=docInfo.title;
00569 if (!strText.isEmpty())
00570 {
00571 m_strTitle=strText;
00572 kdDebug(30503) << "Found new title " << m_strTitle << endl;
00573 }
00574 return true;
00575 }
00576
00577 bool HtmlWorker::doOpenHead(void)
00578 {
00579 *m_streamOut << "<head>" << endl;
00580
00581
00582 *m_streamOut << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=";
00583 *m_streamOut << getCodec()->mimeName() << '"';
00584 *m_streamOut << (isXML()?" /":"") << ">\n" ;
00585
00586
00587 QString strVersion("$Revision: 466447 $");
00588
00589
00590 *m_streamOut << "<meta name=\"Generator\" content=\"KWord HTML Export Filter Version"
00591 << strVersion.mid( 10 ).remove( '$' )
00592 << "\""<< (isXML()?" /":"")
00593 << ">\n";
00594
00595 if (m_strTitle.isEmpty())
00596 {
00597
00598 kdWarning(30503) << "Title still empty! (HtmlWorker::doOpenHead)" << endl;
00599 m_strTitle=i18n("Untitled Document");
00600 }
00601 *m_streamOut << "<title>"<< escapeHtmlText(m_strTitle) <<"</title>\n";
00602
00603 if( !customCSSURL().isEmpty() )
00604 {
00605 *m_streamOut << "<link ref=\"stylesheet\" type=\"text/css\" href=\"" << customCSSURL() << "\" title=\"Style\" >\n" << endl;
00606 }
00607
00608
00609
00610 return true;
00611 }
00612
00613 bool HtmlWorker::doCloseHead(void)
00614 {
00615 *m_streamOut << "</head>\n";
00616 return true;
00617 }
00618
00619 bool HtmlWorker::doOpenBody(void)
00620 {
00621 *m_streamOut << "<body>\n";
00622 return true;
00623 }
00624
00625 bool HtmlWorker::doCloseBody(void)
00626 {
00627 *m_streamOut << "</body>\n";
00628 return true;
00629 }
00630
00631 bool HtmlWorker::doOpenTextFrameSet(void)
00632 {
00633 return true;
00634 }
00635
00636 bool HtmlWorker::doCloseTextFrameSet(void)
00637 {
00638 if (!m_listStack.isEmpty())
00639 {
00640 for (uint i=m_listStack.size(); i>0; i--)
00641 {
00642 ListInfo oldList=m_listStack.pop();
00643 if (oldList.m_orderedList)
00644 {
00645 *m_streamOut << "</ol>\n";
00646 }
00647 else
00648 {
00649 *m_streamOut << "</ul>\n";
00650 }
00651 }
00652 }
00653 return true;
00654 }