00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "serializer.h"
00025 #include "scribusdoc.h"
00026 #include "scribusstructs.h"
00027 #include "pageitem.h"
00028 #include "sccolor.h"
00029 #include "scpattern.h"
00030 #include "util.h"
00031 #include "util_math.h"
00032 #include "util_color.h"
00033 #include "resourcecollection.h"
00034
00035 #include "desaxe/simple_actions.h"
00036 #include "desaxe/saxXML.h"
00037 #include "desaxe/uniqueid.h"
00038
00039 #include <QTextCodec>
00040 #include <QList>
00041 #include <QDebug>
00042
00043 using namespace desaxe;
00044
00045
00046 struct Collection
00047 {
00048 QList<PageItem*> items;
00049 ColorList colors;
00050 StyleSet<ParagraphStyle> pstyles;
00051 StyleSet<CharStyle> cstyles;
00052 QMap<QString,multiLine> lstyles;
00053 QList<QString> fonts;
00054 QList<QString> patterns;
00055
00056 void collectItem(PageItem* p) { items.append(p); }
00057 void collectColor(QString name, ScColor c) { colors[name] = c; }
00058 void collectStyle(ParagraphStyle* style) { if (style && !style->name().isEmpty()) pstyles.append(style); }
00059 void collectCharStyle(CharStyle* style) { if (style && !style->name().isEmpty()) cstyles.append(style); }
00060 void collectLineStyle(QString name, multiLine& m) { lstyles[name] = m; }
00061 void collectFont(QString name) { fonts.append(name); }
00062 void collectPattern(QString name) { patterns.append(name); }
00063 };
00064
00065
00066 class CollectColor_body : public Action_body
00067 {
00068 void begin (const Xml_string& tagname, Xml_attr attr)
00069 {
00070 m_name = attr["name"];
00071 }
00072
00073 void end (const Xml_string& tagname)
00074 {
00075
00076 Collection* coll = this->dig->lookup<Collection>("<collection>");
00077 ScColor* color = this->dig->top<ScColor>();
00078 coll->collectColor(m_name, *color);
00079 }
00080 private:
00081 QString m_name;
00082 };
00083
00084 class CollectColor : public MakeAction<CollectColor_body>
00085 {};
00086
00087 class CollectMultiLine_body : public Action_body
00088 {
00089 void begin (const Xml_string& tagname, Xml_attr attr)
00090 {
00091 m_name = attr["Name"];
00092 }
00093
00094 void end (const Xml_string& tagname)
00095 {
00096
00097 Collection* coll = this->dig->lookup<Collection>("<collection>");
00098 multiLine* mline = this->dig->top<multiLine>();
00099 coll->collectLineStyle(m_name, *mline);
00100 }
00101 private:
00102 QString m_name;
00103 };
00104
00105 class CollectMultiLine : public MakeAction<CollectMultiLine_body>
00106 {};
00107
00108 class CollectSingleLine_body : public Action_body
00109 {
00110 void begin (const Xml_string& tagname, Xml_attr attr)
00111 {
00112 }
00113
00114 void end (const Xml_string& tagname)
00115 {
00116
00117
00118 multiLine* mline = this->dig->lookup<multiLine>("<multiline>");
00119 SingleLine* sline = this->dig->top<SingleLine>();
00120 mline->append(*sline);
00121 }
00122 };
00123
00124 class CollectSingleLine : public MakeAction<CollectSingleLine_body>
00125 {};
00126
00127 Serializer::Serializer(ScribusDoc& doc) : Digester(), m_Doc(doc)
00128 {
00129
00130 addRule("/SCRIBUSFRAGMENT", Factory<Collection>());
00131 addRule("/SCRIBUSFRAGMENT", Store<Collection>("<collection>"));
00132
00133 addRule("/SCRIBUSFRAGMENT/color", Factory<ScColor>());
00134 addRule("/SCRIBUSFRAGMENT/color", SetAttribute<ScColor, QString>( &ScColor::setNamedColor, "RGB" ));
00135 addRule("/SCRIBUSFRAGMENT/color", SetAttribute<ScColor, QString>( &ScColor::setNamedColor, "CMYK" ));
00136 addRule("/SCRIBUSFRAGMENT/color", SetAttributeWithConversion<ScColor, bool>( &ScColor::setSpotColor, "Spot", &parseBool ));
00137 addRule("/SCRIBUSFRAGMENT/color", SetAttributeWithConversion<ScColor, bool>( &ScColor::setRegistrationColor, "Register", &parseBool ));
00138 addRule("/SCRIBUSFRAGMENT/color", CollectColor());
00139
00140 CharStyle::desaxeRules("/SCRIBUSFRAGMENT/", *this);
00141 addRule("/SCRIBUSFRAGMENT/charstyle", SetterP<Collection, CharStyle>( & Collection::collectCharStyle ));
00142
00143 ParagraphStyle::desaxeRules("/SCRIBUSFRAGMENT/", *this);
00144 addRule("/SCRIBUSFRAGMENT/style", SetterP<Collection, ParagraphStyle>( & Collection::collectStyle ));
00145
00146 addRule("/SCRIBUSFRAGMENT/MultiLine", Factory<multiLine>());
00147 addRule("/SCRIBUSFRAGMENT/MultiLine", Store<multiLine>("<multiline>"));
00148 addRule("/SCRIBUSFRAGMENT/MultiLine", CollectMultiLine());
00149
00150 addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", Factory<SingleLine>());
00151 addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, const QString&> ( &SingleLine::setColor, "Color", &parse<const Xml_string&>, "Black"));
00152 addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, int>( &SingleLine::setShade, "Shade", &parseInt ));
00153 addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, int>( &SingleLine::setDash , "Dash", &parseInt ));
00154 addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, int>( &SingleLine::setLineEnd , "LineEnd", &parseInt ));
00155 addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, int>( &SingleLine::setLineJoin, "LineJoin", &parseInt ));
00156 addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, double>( &SingleLine::setLineWidth, "Width", &parseDouble ));
00157 addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", CollectSingleLine());
00158
00159 addRule("/SCRIBUSFRAGMENT/font", SetAttribute<Collection, QString>( & Collection::collectFont, "name"));
00160
00161 PageItem::desaxeRules("", *this, "item");
00162 addRule("/SCRIBUSFRAGMENT/item", SetterP<Collection,PageItem>( & Collection::collectItem ));
00163 }
00164
00165
00166 void Serializer::serializeObjects(const Selection& selection, SaxHandler& outputhandler)
00167 {
00168 Xml_attr attr;
00169 UniqueID handler( & outputhandler );
00170 handler.beginDoc();
00171 handler.begin("SCRIBUSFRAGMENT", attr);
00172 ScribusDoc* doc = selection.itemAt(0)->doc();
00173
00174
00175 QMap<QString,int>::Iterator itf;
00176 for (itf = doc->UsedFonts.begin(); itf != doc->UsedFonts.end(); ++itf)
00177 {
00178 attr["name"] = itf.key();
00179 handler.beginEnd("font", attr);
00180 }
00181
00182 ColorList usedColors;
00183 doc->getUsedColors(usedColors, false);
00184 ColorList::Iterator itc;
00185 for (itc = usedColors.begin(); itc != usedColors.end(); ++itc)
00186 {
00187 Xml_attr cattr;
00188 cattr["name"] = itc.key();
00189 if (doc->PageColors[itc.key()].getColorModel() == colorModelRGB)
00190 cattr["RGB"] = doc->PageColors[itc.key()].nameRGB();
00191 else
00192 cattr["CMYK"] = doc->PageColors[itc.key()].nameCMYK();
00193 cattr["Spot"] = toXMLString(doc->PageColors[itc.key()].isSpotColor());
00194 cattr["Register"] = toXMLString(doc->PageColors[itc.key()].isRegistrationColor());
00195 handler.beginEnd("color", cattr);
00196 }
00197
00198 ResourceCollection lists;
00199 for (int i=0; i < doc->Items->count(); ++i)
00200 doc->Items->at(i)->getNamedResources(lists);
00201
00202 QList<QString>::Iterator it;
00203 QList<QString> names = lists.styleNames();
00204 for (it = names.begin(); it != names.end(); ++it)
00205 doc->paragraphStyles().get(*it).saxx(handler);
00206
00207 names = lists.charStyleNames();
00208 for (it = names.begin(); it != names.end(); ++it)
00209 doc->charStyles().get(*it).saxx(handler);
00210
00211 names = lists.lineStyleNames();
00212 for (it = names.begin(); it != names.end(); ++it)
00213 {
00214 Xml_attr multiattr;
00215 multiattr["Name"] = *it;
00216 handler.begin("MultiLine", multiattr);
00217 multiLine ml = doc->MLineStyles[*it];
00218
00219 multiLine::Iterator itMU2;
00220 for (itMU2 = ml.begin(); itMU2 != ml.end(); ++itMU2)
00221 {
00222 Xml_attr lineattr;
00223 lineattr["Color"] = (*itMU2).Color;
00224 lineattr["Shade"] = toXMLString((*itMU2).Shade);
00225 lineattr["Dash"] = toXMLString((*itMU2).Dash);
00226 lineattr["LineEnd"] = toXMLString((*itMU2).LineEnd);
00227 lineattr["LineJoin"] = toXMLString((*itMU2).LineJoin);
00228 lineattr["Width"] = toXMLString((*itMU2).Width);
00229 handler.beginEnd("SubLine", lineattr);
00230 }
00231 handler.end("MultiLine");
00232 }
00233
00234
00235
00236
00237
00238
00239 for (int i=0; i < doc->Items->count(); ++i)
00240 {
00241 int k = selection.findItem(doc->Items->at(i));
00242 if (k >=0)
00243 doc->Items->at(i)->saxx(handler);
00244 }
00245
00246 handler.end("SCRIBUSFRAGMENT");
00247 handler.endDoc();
00248 }
00249
00250
00251 Selection Serializer::deserializeObjects(const QByteArray & xml)
00252 {
00253 backUpColors = m_Doc.PageColors;
00254 store<ScribusDoc>("<scribusdoc>", &m_Doc);
00255
00256 parseMemory(xml, xml.length());
00257
00258 return importCollection();
00259 }
00260
00261 Selection Serializer::deserializeObjects(const QFile & file)
00262 {
00263 backUpColors = m_Doc.PageColors;
00264 store<ScribusDoc>("<scribusdoc>", &m_Doc);
00265
00266 QFileInfo fi(file);
00267 parseFile(fi.filePath());
00268
00269 return importCollection();
00270 }
00271
00272
00273 Selection Serializer::importCollection()
00274 {
00275 Collection* coll = lookup<Collection>("<collection>");
00276 Selection result( &m_Doc, false);
00277
00278 if (coll == NULL)
00279 qDebug("deserialize: no objects collected");
00280 else
00281 {
00282 QMap<QString,QString> newNames;
00283
00284
00285
00286 do {
00287 newNames.clear();
00288 for (int i = 0; i < coll->cstyles.count(); ++i)
00289 {
00290 QString oldName = coll->cstyles[i].name();
00291 int oldIndex = m_Doc.charStyles().find(oldName);
00292 if (oldIndex >= 0 && m_Doc.charStyle(oldName) == coll->cstyles[i])
00293 continue;
00294 QString newName = oldName;
00295 if (oldIndex >= 0 && !newNames.contains(oldName))
00296 {
00297 int counter = 0;
00298 while (m_Doc.charStyles().find(newName) >= 0)
00299 newName = (QObject::tr("Copy of %1 (%2)")).arg(oldName).arg(++counter);
00300 newNames[oldName] = newName;
00301 }
00302 }
00303
00304 coll->cstyles.rename(newNames);
00305 }
00306 while (newNames.count() > 0);
00307 m_Doc.redefineCharStyles(coll->cstyles, false);
00308
00309 do {
00310 newNames.clear();
00311 for (int i = 0; i < coll->pstyles.count(); ++i)
00312 {
00313 QString oldName = coll->pstyles[i].name();
00314 int oldIndex = m_Doc.paragraphStyles().find(oldName);
00315
00316
00317
00318
00319
00320 if (oldIndex >= 0 && coll->pstyles[i] == m_Doc.paragraphStyle(oldName) )
00321 continue;
00322 QString newName = oldName;
00323 if (oldIndex >= 0 && !newNames.contains(oldName))
00324 {
00325 int counter = 0;
00326 while (m_Doc.paragraphStyles().find(newName) >= 0)
00327 newName = (QObject::tr("Copy of %1 (%2)")).arg(oldName).arg(++counter);
00328 newNames[oldName] = newName;
00329 }
00330 }
00331 coll->pstyles.rename(newNames);
00332 }
00333 while(newNames.count() > 0);
00334
00335 m_Doc.redefineStyles(coll->pstyles, false);
00336
00337
00338 QMap<QString,multiLine>::Iterator mlit;
00339 for (mlit = coll->lstyles.begin(); mlit != coll->lstyles.end(); ++mlit)
00340 {
00341 multiLine& ml = mlit.value();
00342 QString oldName = mlit.key();
00343 QString newName = mlit.key();
00344 QMap<QString,multiLine>::ConstIterator mlitd = m_Doc.MLineStyles.find(oldName);
00345 if (mlitd != m_Doc.MLineStyles.end() && ml != mlitd.value())
00346 {
00347 int counter = 0;
00348 while (m_Doc.MLineStyles.contains(newName))
00349 newName = (QObject::tr("Copy of %1 (%2)")).arg(oldName).arg(++counter);
00350 }
00351 m_Doc.MLineStyles.insert(newName, ml);
00352 }
00353
00354
00355
00356 QList<PageItem*>* objects = &(coll->items);
00357 m_Doc.PageColors = backUpColors;
00358 m_Doc.PageColors.addColors(coll->colors, false);
00359 for (int i=0; i < objects->count(); ++i)
00360 {
00361 PageItem* currItem = objects->at(i);
00362 currItem->Clip = FlattenPath(currItem->PoLine, currItem->Segments);
00363 currItem->setFillQColor();
00364 currItem->setLineQColor();
00365 result.addItem(currItem);
00366 }
00367 updateGradientColors(coll->colors);
00368 delete coll;
00369 }
00370 return result;
00371 }
00372
00373
00374 bool Serializer::writeWithEncoding(const QString& filename, const QString& encoding,
00375 const QString& txt)
00376 {
00377 QTextCodec *codec;
00378 if (encoding.isEmpty())
00379 codec = QTextCodec::codecForLocale();
00380 else
00381 codec = QTextCodec::codecForName(encoding.toLocal8Bit());
00382 QByteArray dec = codec->fromUnicode( txt );
00383 QFile f(filename);
00384 if (f.open(QIODevice::WriteOnly))
00385 {
00386 f.write(dec, dec.length());
00387 f.close();
00388 return true;
00389 }
00390 return false;
00391 }
00392
00393
00394 bool Serializer::readWithEncoding(const QString& filename, const QString& encoding,
00395 QString &txt)
00396 {
00397 QByteArray file;
00398 QTextCodec *codec;
00399 if (encoding.isEmpty())
00400 codec = QTextCodec::codecForLocale();
00401 else
00402 codec = QTextCodec::codecForName(encoding.toLocal8Bit());
00403 if (loadRawText(filename, file))
00404 {
00405 txt = codec->toUnicode( file.data() );
00406 return true;
00407 }
00408 return false;
00409 }
00410
00411 void Serializer::updateGradientColors(const ColorList& colors)
00412 {
00413 VColorStop* grStop;
00414 uint itemsCount = m_Doc.Items->count();
00415 for (uint c=0; c < itemsCount; ++c)
00416 {
00417 PageItem *ite = m_Doc.Items->at(c);
00418 QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
00419 for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
00420 {
00421 grStop = cstops.at(cst);
00422 if (colors.contains(grStop->name))
00423 grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
00424 }
00425 }
00426 uint masterItemsCount = m_Doc.MasterItems.count();
00427 for (uint c=0; c < masterItemsCount; ++c)
00428 {
00429 PageItem *ite = m_Doc.MasterItems.at(c);
00430 QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
00431 for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
00432 {
00433 grStop = cstops.at(cst);
00434 if (colors.contains(grStop->name))
00435 grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
00436 }
00437 }
00438 uint frameItemsCount = m_Doc.FrameItems.count();
00439 for (uint c=0; c < frameItemsCount; ++c)
00440 {
00441 PageItem *ite = m_Doc.FrameItems.at(c);
00442 QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
00443 for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
00444 {
00445 grStop = cstops.at(cst);
00446 if (colors.contains(grStop->name))
00447 grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
00448 }
00449 }
00450 QStringList patterns =m_Doc.docPatterns.keys();
00451 for (int c = 0; c < patterns.count(); ++c)
00452 {
00453 ScPattern& pa = m_Doc.docPatterns[patterns[c]];
00454 for (int o = 0; o < pa.items.count(); o++)
00455 {
00456 PageItem *ite = pa.items.at(o);
00457 QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
00458 for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
00459 {
00460 grStop = cstops.at(cst);
00461 if (colors.contains(grStop->name))
00462 grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
00463 }
00464 }
00465 }
00466 }