Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

contentreader.cpp

Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008  *   Copyright (C) 2004 by Riku Leino                                      *
00009  *   tsoots@gmail.com                                                      *
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  *   This program is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00019  *   GNU General Public License for more details.                          *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU General Public License     *
00022  *   along with this program; if not, write to the                         *
00023  *   Free Software Foundation, Inc.,                                       *
00024  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00025  ***************************************************************************/
00026 
00027 #include <QGlobalStatic>
00028 #include <QByteArray>
00029 #include "contentreader.h"
00030 #include "scribusstructs.h"
00031 
00032 ContentReader* ContentReader::creader = NULL;
00033 
00034 extern xmlSAXHandlerPtr cSAXHandler;
00035 
00036 ContentReader::ContentReader(QString documentName, StyleReader *s, gtWriter *w, bool textOnly)
00037 {
00038     creader = this;
00039     docname = documentName;
00040     sreader = s;
00041     writer  = w;
00042     importTextOnly = textOnly;
00043     defaultStyle = NULL;
00044     currentStyle = NULL;
00045     append = false;
00046     inList = false;
00047     inNote = false;
00048     inNoteBody = false;
00049     inSpan = false;
00050     listIndex = 0;
00051     listLevel = 0;
00052     currentList = "";
00053     currentListStyle = 0;
00054     inT = false;
00055     tName = "";
00056 }
00057 
00058 bool ContentReader::startElement(const QString&, const QString&, const QString &name, const QXmlAttributes &attrs) 
00059 {
00060     if ((name == "text:p") || (name == "text:h"))
00061     {
00062         append = true;
00063         QString name = "";
00064         for (int i = 0; i < attrs.count(); ++i)
00065         {
00066             if (attrs.localName(i) == "text:style-name")
00067             {
00068                 name = attrs.value(i);
00069                 styleNames.push_back(attrs.value(i));
00070             }
00071         }
00072         if (!inList)
00073         {
00074             pstyle = sreader->getStyle(name);
00075             currentStyle = pstyle;
00076         }
00077         else
00078         {
00079             gtStyle *tmp = sreader->getStyle(getName());
00080             if ((tmp->getName()).indexOf("default-style") != -1)
00081                 getStyle();
00082             else
00083                 currentStyle = tmp;
00084         }
00085     }
00086     else if (name == "text:span")
00087     {
00088         inSpan = true;
00089         QString styleName = "";
00090         for (int i = 0; i < attrs.count(); ++i)
00091         {
00092             if (attrs.localName(i) == "text:style-name")
00093             {
00094                 currentStyle = sreader->getStyle(attrs.value(i));
00095                 styleName = attrs.value(i);
00096                 styleNames.push_back(styleName);
00097             }
00098         }
00099         gtStyle *tmp = sreader->getStyle(getName());
00100         if ((tmp->getName()).indexOf("default-style") != -1)
00101             getStyle();
00102         else
00103             currentStyle = tmp;
00104     }
00105     else if (name == "text:list")
00106     {
00107         inList = true;
00108         ++listLevel;
00109         if (static_cast<int>(listIndex2.size()) < listLevel)
00110             listIndex2.push_back(0);
00111         for (int i = 0; i < attrs.count(); ++i)
00112         {
00113             if (attrs.localName(i) == "text:style-name")
00114                 currentList = attrs.value(i);
00115         }
00116         currentStyle = sreader->getStyle(QString(currentList + "_%1").arg(listLevel));
00117         currentListStyle = sreader->getList(currentList);
00118         currentListStyle->setLevel(listLevel);
00119         styleNames.clear();
00120         styleNames.push_back(QString(currentList + "_%1").arg(listLevel));
00121     }
00122     else if (name == "text:list-item")
00123     {
00124         currentListStyle->advance();
00125         write(currentListStyle->bullet());
00126     }
00127     else if (name == "text:note")
00128         inNote = true;
00129     else if (name == "text:note-body")
00130         inNoteBody = true;
00131     else if (name == "style:style")
00132     {
00133         QString sname = "";
00134         bool isTextStyle = false;
00135         for (int i = 0; i < attrs.count(); ++i)
00136         {
00137             if (attrs.localName(i) == "style:name")
00138                 sname = attrs.value(i);
00139             else if ((attrs.localName(i) == "style:family") && (attrs.value(i) == "text"))
00140                 isTextStyle = true;
00141         }
00142         if (isTextStyle)
00143         {
00144             tName = sname;
00145             inT = true;
00146         }
00147     }
00148     else if ((name == "style:paragraph-properties" ||
00149               name == "style:text-properties" ||
00150               name == "style:list-level-properties") && (inT))
00151     {
00152         Properties p;
00153         for (int i = 0; i < attrs.count(); ++i)
00154         {
00155             std::pair<QString, QString> pair(attrs.localName(i), attrs.value(i));
00156             p.push_back(pair);
00157         }
00158         tmap[tName] = p;
00159     }
00160     else if (name == "text:s")
00161     {
00162         int count = 1;
00163         for (int i = 0; i < attrs.count(); ++i)
00164         {
00165             if (attrs.localName(i) == "text:c")
00166             {
00167                 bool ok = false;
00168                 int tmpcount = (attrs.value(i)).toInt(&ok);
00169                 if (ok)
00170                     count = tmpcount;
00171             }
00172         }
00173         for (int i = 0; i < count; ++i)
00174             write(" ");
00175     }
00176     return true;
00177 }
00178 
00179 bool ContentReader::characters(const QString &ch) 
00180 {
00181     QString tmp = ch;
00182     tmp = tmp.remove("\n");
00183     tmp = tmp.remove(""); // Remove all OO.o hyphenation chars
00184     tmp = tmp.replace(QChar(160), SpecialChars::NBSPACE); // replace OO.o nbsp with Scribus nbsp
00185     if (append)
00186         write(tmp);
00187     return true;
00188 }
00189 
00190 bool ContentReader::endElement(const QString&, const QString&, const QString &name)
00191 {
00192     if ((name == "text:p") || (name == "text:h"))
00193     {
00194         write("\n");
00195         append = false;
00196         if (inList || inNote || inNoteBody)
00197             styleNames.pop_back();
00198         else
00199             styleNames.clear();
00200     }
00201     else if (name == "text:span")
00202     {
00203         inSpan = false;
00204         currentStyle = pstyle;
00205         if (styleNames.size() != 0)
00206             styleNames.pop_back();  
00207         currentStyle = sreader->getStyle(getName());
00208     }
00209     else if (name == "text:note")
00210         inNote = false;
00211     else if (name == "text:note-body")
00212         inNoteBody = false;
00213     else if (name == "text:line-break")
00214         write(SpecialChars::LINEBREAK);
00215     else if (name == "text:tab")
00216         write("\t");
00217     else if (name == "text:list")
00218     {
00219         --listLevel;
00220         styleNames.clear();
00221         if (listLevel == 0)
00222         {
00223             inList = false;
00224             listIndex2.clear();
00225             currentListStyle = 0;
00226         }
00227         else
00228         {
00229             currentStyle = sreader->getStyle(QString(currentList + "_%1").arg(listLevel));
00230             styleNames.push_back(QString(currentList + "_%1").arg(listLevel));
00231             currentListStyle->resetLevel();
00232             currentListStyle = sreader->getList(currentList);
00233             currentListStyle->setLevel(listLevel);
00234         }
00235     }
00236     else if ((name == "style:style") && (inT))
00237     {
00238         inT = false;
00239         tName = "";
00240     }
00241     return true;
00242 }
00243 
00244 void ContentReader::write(const QString& text)
00245 {
00246     if (!inNote && !inNoteBody) // Disable notes import for now
00247     {
00248         if (importTextOnly)
00249             writer->append(text);
00250         else if (inSpan)
00251             writer->append(text, currentStyle, false);
00252         else
00253             writer->append(text, currentStyle);
00254     }
00255     lastStyle = currentStyle;
00256 }
00257 
00258 void ContentReader::parse(QString fileName)
00259 {
00260     sreader->parse(fileName);
00261 #if defined(_WIN32)
00262     QString fname = QDir::convertSeparators(fileName);
00263     QByteArray fn = (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) ? fname.toUtf8() : fname.toLocal8Bit();
00264 #else
00265     QByteArray fn(fileName.toLocal8Bit());
00266 #endif
00267     xmlSAXParseFile(cSAXHandler, fn.data(), 1);
00268 }
00269 
00270 xmlSAXHandler cSAXHandlerStruct = {
00271     NULL, // internalSubset,
00272     NULL, // isStandalone,
00273     NULL, // hasInternalSubset,
00274     NULL, // hasExternalSubset,
00275     NULL, // resolveEntity,
00276     NULL, // getEntity,
00277     NULL, // entityDecl,
00278     NULL, // notationDecl,
00279     NULL, // attributeDecl,
00280     NULL, // elementDecl,
00281     NULL, // unparsedEntityDecl,
00282     NULL, // setDocumentLocator,
00283     NULL, // startDocument,
00284     NULL, // endDocument,
00285     ContentReader::startElement,
00286     ContentReader::endElement,
00287     NULL, // reference,
00288     ContentReader::characters,
00289     NULL, // ignorableWhitespace,
00290     NULL, // processingInstruction,
00291     NULL, // comment,
00292     NULL, // warning,
00293     NULL, // error,
00294     NULL, // fatalError,
00295     NULL, // getParameterEntity,
00296     NULL, // cdata,
00297     NULL,
00298     1
00299 #ifdef HAVE_XML26
00300     ,
00301     NULL,
00302     NULL,
00303     NULL,
00304     NULL
00305 #endif
00306 };
00307 
00308 xmlSAXHandlerPtr cSAXHandler = &cSAXHandlerStruct;
00309 
00310 void ContentReader::startElement(void*, const xmlChar *fullname, const xmlChar ** atts)
00311 {
00312     QString* name = new QString((const char*) fullname);
00313     name = new QString(name->toLower());
00314     QXmlAttributes* attrs = new QXmlAttributes();
00315     if (atts)
00316     {
00317         for(const xmlChar** cur = atts; cur && *cur; cur += 2)
00318             attrs->append(QString((char*)*cur), NULL, QString((char*)*cur), QString((char*)*(cur + 1)));
00319     }
00320     creader->startElement(NULL, NULL, *name, *attrs);
00321 }
00322 
00323 void ContentReader::characters(void*, const xmlChar *ch, int len)
00324 {
00325     QString chars = QString::fromUtf8((const char*) ch, len);
00326     creader->characters(chars);
00327 }
00328 
00329 void ContentReader::endElement(void*, const xmlChar *name)
00330 {
00331     QString *nname = new QString((const char*) name);
00332     nname = new QString(nname->toLower());
00333     creader->endElement(NULL, NULL, *nname);
00334 }
00335 
00336 QString ContentReader::getName()
00337 {
00338     QString s = "";
00339     for (uint i = 0; i < styleNames.size(); ++i)
00340         s += styleNames[i];
00341     return s;
00342 }
00343 
00344 void ContentReader::getStyle()
00345 {
00346     gtParagraphStyle* par = NULL;
00347     if (styleNames.size() == 0)
00348         par = dynamic_cast<gtParagraphStyle*>(sreader->getStyle("default-style"));
00349     else
00350         par = dynamic_cast<gtParagraphStyle*>(sreader->getStyle(styleNames[0]));
00351     assert(par != NULL);
00352     gtParagraphStyle* tmp = new gtParagraphStyle(*par);
00353     for (uint i = 1; i < styleNames.size(); ++i)
00354     {
00355         Properties& p = tmap[styleNames[i]];
00356         for (uint j = 0; j < p.size(); ++j)
00357             sreader->updateStyle(tmp, sreader->getStyle(styleNames[i - 1]), p[j].first, p[j].second);
00358     }
00359 
00360     currentStyle = tmp;
00361     sreader->setStyle(getName(), tmp);
00362 }
00363 
00364 ContentReader::~ContentReader()
00365 {
00366     creader = NULL;
00367     delete defaultStyle;
00368 }
Created with personalized Doxygen. This is documentation for GPL software Scribus - Open Source Desktop Publishing.