Subversion Repositories Scribus

Rev

Rev 9553 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
3 paul 7
/***************************************************************************
8
                          serializer.cpp  -  description
9
                             -------------------
10
    begin                : Sat May 5 2001
11
    copyright            : (C) 2001 by Franz Schmid
12
    email                : Franz.Schmid@altmuehlnet.de
13
 ***************************************************************************/
14
 
15
/***************************************************************************
16
 *                                                                         *
17
 *   This program is free software; you can redistribute it and/or modify  *
18
 *   it under the terms of the GNU General Public License as published by  *
19
 *   the Free Software Foundation; either version 2 of the License, or     *
20
 *   (at your option) any later version.                                   *
21
 *                                                                         *
22
 ***************************************************************************/
23
 
24
#include "serializer.h"
217 Franz 25
#include "scribusdoc.h"
456 fschmid 26
#include "pageitem.h"
8841 avox 27
#include <cassert>
3 paul 28
#include <qfile.h>
29
#include <qtextstream.h>
30
#include <qtextcodec.h>
8398 avox 31
#include "sccolor.h"
5064 cbradney 32
#include "util.h"
9553 jghali 33
#include "colorutil.h"
8455 avox 34
#include "resourcecollection.h"
35
 
8266 avox 36
#include "desaxe/simple_actions.h"
37
#include "desaxe/saxXML.h"
8382 avox 38
#include "desaxe/uniqueid.h"
2534 craig 39
 
8382 avox 40
 
8266 avox 41
using namespace desaxe;
42
 
43
 
8412 avox 44
struct Collection
45
{
46
        QPtrList<PageItem> items;
47
        ColorList colors;
48
        StyleSet<ParagraphStyle> pstyles;
49
        StyleSet<CharStyle> cstyles;
9402 jghali 50
        QMap<QString,multiLine> lstyles;
8412 avox 51
        QValueList<QString> fonts;
52
        QValueList<QString> patterns;
53
 
54
        void collectItem(PageItem* p)              { items.append(p); }
55
        void collectColor(QString name, ScColor c) { colors[name] = c; }
8464 avox 56
        void collectStyle(ParagraphStyle* style)   { if (style && !style->name().isEmpty()) pstyles.append(style); }
57
        void collectCharStyle(CharStyle* style)    { if (style && !style->name().isEmpty()) cstyles.append(style); }
9402 jghali 58
        void collectLineStyle(QString name, multiLine& m) { lstyles[name] = m; }
8412 avox 59
        void collectFont(QString name)             { fonts.append(name); }
60
        void collectPattern(QString name)          { patterns.append(name); }
61
};
62
 
63
 
64
class CollectColor_body : public Action_body
65
{
9402 jghali 66
        void begin (const Xml_string& tagname, Xml_attr attr)
8412 avox 67
        {
68
                m_name = attr["name"];
69
        }
70
 
9402 jghali 71
        void end (const Xml_string& tagname)
8412 avox 72
        {
8464 avox 73
//              qDebug(QString("collect %1").arg(tagname));
8832 avox 74
                Collection* coll = this->dig->lookup<Collection>("<collection>");
8412 avox 75
                ScColor* color = this->dig->top<ScColor>();
76
                coll->collectColor(m_name, *color);
77
        }
78
private:
79
        QString m_name;
80
};
81
 
82
class CollectColor : public MakeAction<CollectColor_body>
83
{};
84
 
9402 jghali 85
class CollectMultiLine_body : public Action_body
86
{
87
        void begin (const Xml_string& tagname, Xml_attr attr)
88
        {
89
                m_name = attr["Name"];
90
        }
91
 
92
        void end (const Xml_string& tagname)
93
        {
94
//              qDebug(QString("collect %1").arg(tagname));
95
                Collection* coll  = this->dig->lookup<Collection>("<collection>");
96
                multiLine*  mline = this->dig->top<multiLine>();
97
                coll->collectLineStyle(m_name, *mline);
98
        }
99
private:
100
        QString m_name;
101
};
8412 avox 102
 
9402 jghali 103
class CollectMultiLine : public MakeAction<CollectMultiLine_body>
104
{};
105
 
106
class CollectSingleLine_body : public Action_body
107
{
108
        void begin (const Xml_string& tagname, Xml_attr attr)
109
        {
110
        }
111
 
112
        void end (const Xml_string& tagname)
113
        {
114
//              qDebug(QString("collect %1").arg(tagname));
9589 avox 115
//              Collection* coll  = this->dig->lookup<Collection>("<collection>");
9402 jghali 116
                multiLine*  mline = this->dig->lookup<multiLine>("<multiline>");
117
                SingleLine* sline = this->dig->top<SingleLine>();
118
                mline->append(*sline);
119
        }
120
};
121
 
122
class CollectSingleLine : public MakeAction<CollectSingleLine_body>
123
{};
124
 
125
 
8193 avox 126
Serializer::Serializer(ScribusDoc& doc) : Digester(), m_Doc(doc)
3 paul 127
{
8193 avox 128
        // register desaxe rules for styles, colors and elems
8412 avox 129
        addRule("/SCRIBUSFRAGMENT", Factory<Collection>());
130
        addRule("/SCRIBUSFRAGMENT", Store<Collection>("<collection>"));
8398 avox 131
 
132
        addRule("/SCRIBUSFRAGMENT/color", Factory<ScColor>());
133
        addRule("/SCRIBUSFRAGMENT/color", SetAttribute<ScColor, QString>( &ScColor::setNamedColor, "RGB" ));
134
        addRule("/SCRIBUSFRAGMENT/color", SetAttribute<ScColor, QString>( &ScColor::setNamedColor, "CMYK" ));
135
        addRule("/SCRIBUSFRAGMENT/color", SetAttributeWithConversion<ScColor, bool>( &ScColor::setSpotColor, "Spot", &parseBool ));
136
        addRule("/SCRIBUSFRAGMENT/color", SetAttributeWithConversion<ScColor, bool>( &ScColor::setRegistrationColor, "Register", &parseBool ));
8412 avox 137
        addRule("/SCRIBUSFRAGMENT/color", CollectColor());
8398 avox 138
 
8412 avox 139
        CharStyle::desaxeRules("/SCRIBUSFRAGMENT/", *this);
140
        addRule("/SCRIBUSFRAGMENT/charstyle", SetterP<Collection, CharStyle>( & Collection::collectCharStyle ));
141
 
142
        ParagraphStyle::desaxeRules("/SCRIBUSFRAGMENT/", *this);
143
        addRule("/SCRIBUSFRAGMENT/style", SetterP<Collection, ParagraphStyle>( & Collection::collectStyle ));
144
 
9402 jghali 145
        addRule("/SCRIBUSFRAGMENT/MultiLine", Factory<multiLine>());
146
        addRule("/SCRIBUSFRAGMENT/MultiLine", Store<multiLine>("<multiline>"));
147
        addRule("/SCRIBUSFRAGMENT/MultiLine", CollectMultiLine());
148
 
149
        addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", Factory<SingleLine>());
150
        addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, const QString&> ( &SingleLine::setColor, "Color", &parse<const Xml_string&>, "Black"));
151
        addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, int>( &SingleLine::setShade, "Shade", &parseInt ));
152
        addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, int>( &SingleLine::setDash , "Dash", &parseInt ));
153
        addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, int>( &SingleLine::setLineEnd , "LineEnd", &parseInt ));
154
        addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, int>( &SingleLine::setLineJoin, "LineJoin", &parseInt ));
155
        addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", SetAttributeWithConversion<SingleLine, double>( &SingleLine::setLineWidth, "Width", &parseDouble ));
156
        addRule("/SCRIBUSFRAGMENT/MultiLine/SubLine", CollectSingleLine());
157
 
8412 avox 158
        addRule("/SCRIBUSFRAGMENT/font", SetAttribute<Collection, QString>( & Collection::collectFont, "name"));
159
 
8289 avox 160
        PageItem::desaxeRules("", *this, "item");
8412 avox 161
        addRule("/SCRIBUSFRAGMENT/item", SetterP<Collection,PageItem>( & Collection::collectItem ));
3 paul 162
}
163
 
164
 
8382 avox 165
void Serializer::serializeObjects(const Selection& selection, SaxHandler& outputhandler)
8266 avox 166
{
8841 avox 167
        assert (selection.count() > 0);
8289 avox 168
        Xml_attr attr;
8382 avox 169
        UniqueID handler( & outputhandler );
8289 avox 170
        handler.beginDoc();
171
        handler.begin("SCRIBUSFRAGMENT", attr);
8328 avox 172
        ScribusDoc* doc = selection.itemAt(0)->doc();
8398 avox 173
 
174
 
175
        QMap<QString,int>::Iterator itf;
176
        for (itf = doc->UsedFonts.begin(); itf != doc->UsedFonts.end(); ++itf)
177
        {
178
                attr["name"] = itf.key();
179
                handler.beginEnd("font", attr);
180
        }
181
 
182
        ColorList usedColors;
183
        doc->getUsedColors(usedColors, false);
184
        ColorList::Iterator itc;
185
        for (itc = usedColors.begin(); itc != usedColors.end(); ++itc)
186
        {
187
                Xml_attr cattr;
188
                cattr["name"] = itc.key();
189
                if (doc->PageColors[itc.key()].getColorModel() == colorModelRGB)
190
                        cattr["RGB"] = doc->PageColors[itc.key()].nameRGB();
191
                else
192
                        cattr["CMYK"] = doc->PageColors[itc.key()].nameCMYK();
193
                cattr["Spot"] = toXMLString(doc->PageColors[itc.key()].isSpotColor());
194
                cattr["Register"] = toXMLString(doc->PageColors[itc.key()].isRegistrationColor());
195
                handler.beginEnd("color", cattr);
196
        }
197
 
8455 avox 198
        ResourceCollection lists;
8328 avox 199
        for (uint i=0; i < doc->Items->count(); ++i)
8455 avox 200
                doc->Items->at(i)->getNamedResources(lists);
201
 
202
        QValueList<QString>::Iterator it;
203
        QValueList<QString> names = lists.styleNames();
204
        for (it = names.begin(); it != names.end(); ++it)
205
                doc->paragraphStyles()[*it].saxx(handler);
206
 
207
        names = lists.charStyleNames();
208
        for (it = names.begin(); it != names.end(); ++it)
209
                doc->charStyles()[*it].saxx(handler);
210
 
211
        names = lists.lineStyleNames();
212
        for (it = names.begin(); it != names.end(); ++it)
8328 avox 213
        {
8455 avox 214
                Xml_attr multiattr;
215
                multiattr["Name"] = *it;
216
                handler.begin("MultiLine", multiattr);         
217
                multiLine ml = doc->MLineStyles[*it];
218
 
219
                QValueVector<SingleLine>::Iterator itMU2;
220
                for (itMU2 = ml.begin(); itMU2 != ml.end(); ++itMU2)
221
                {
222
                        Xml_attr lineattr;
223
                        lineattr["Color"] = (*itMU2).Color;
8836 avox 224
                        lineattr["Shade"] = toXMLString((*itMU2).Shade);
225
                        lineattr["Dash"] = toXMLString((*itMU2).Dash);
226
                        lineattr["LineEnd"] = toXMLString((*itMU2).LineEnd);
227
                        lineattr["LineJoin"] = toXMLString((*itMU2).LineJoin);
228
                        lineattr["Width"] = toXMLString((*itMU2).Width);
8455 avox 229
                        handler.beginEnd("SubLine", lineattr);
230
                }
231
                handler.end("MultiLine");
232
        }
233
 
234
        /*      names = lists.patterns();
235
        for (it = names.begin(); it != names.end(); ++it)
236
                doc->patterns[*it].saxx(handler);
237
*/
238
 
239
        for (uint i=0; i < doc->Items->count(); ++i)
240
        {
8328 avox 241
                int k = selection.findItem(doc->Items->at(i));
242
                if (k >=0)
243
                        doc->Items->at(i)->saxx(handler);
244
        }
8398 avox 245
 
8289 avox 246
        handler.end("SCRIBUSFRAGMENT");
247
        handler.endDoc();
248
}
3 paul 249
 
250
 
8289 avox 251
Selection Serializer::deserializeObjects(const QCString & xml)
252
{
253
        store<ScribusDoc>("<scribusdoc>", &m_Doc);
8412 avox 254
 
8289 avox 255
        parseMemory(xml, xml.length());
8266 avox 256
 
8412 avox 257
        return importCollection();
8266 avox 258
}
259
 
8328 avox 260
Selection Serializer::deserializeObjects(const QFile & file)
8266 avox 261
{
8289 avox 262
        store<ScribusDoc>("<scribusdoc>", &m_Doc);
8412 avox 263
 
8328 avox 264
        QFileInfo fi(file);
8289 avox 265
        parseFile(fi.filePath());
8412 avox 266
 
267
        return importCollection();
268
}
269
 
270
 
271
Selection Serializer::importCollection()
272
{      
273
        Collection* coll = lookup<Collection>("<collection>");
8289 avox 274
        Selection result( &m_Doc, false);
8455 avox 275
//      qDebug(QString("deserialize: collection %1 doc %2").arg((ulong)coll).arg((ulong)&m_Doc));
276
        if (coll == NULL)
277
                qDebug("deserialize: no objects collected");
278
        else
8289 avox 279
        {
8455 avox 280
                QMap<QString,QString> newNames;
8879 avox 281
 
282
                //TODO: fonts
283
 
284
                do {
285
                        newNames.clear();
286
                        for (uint i = 0; i < coll->cstyles.count(); ++i)  
287
                        {
288
                                QString oldName = coll->cstyles[i].name();
289
                                int oldIndex = m_Doc.charStyles().find(oldName);
290
                                if (oldIndex >= 0 && m_Doc.charStyle(oldName) == coll->cstyles[i])
291
                                        continue;
292
                                QString newName = oldName;
293
                                if (oldIndex >= 0 && !newNames.contains(oldName))
294
                                {
295
                                        int counter = 0;
296
                                        while (m_Doc.charStyles().find(newName) >= 0)
297
                                                newName = (QObject::tr("Copy of %1 (%2)")).arg(oldName).arg(++counter);
298
                                        newNames[oldName] = newName;
299
                                }
300
                        }
301
 
302
                        coll->cstyles.rename(newNames);
8455 avox 303
                }
8879 avox 304
                while (newNames.count() > 0);
305
                m_Doc.redefineCharStyles(coll->cstyles, false);
8455 avox 306
 
8879 avox 307
                do {
308
                        newNames.clear();
309
                        for (uint i = 0; i < coll->pstyles.count(); ++i)  // FIXME:  QValueList<QString> StyleSet::names()
310
                        {
311
                                QString oldName = coll->pstyles[i].name();
312
                                int oldIndex = m_Doc.paragraphStyles().find(oldName);
313
//                              qDebug(QString("comparing %1 (old %2 new %3): parent '%4'='%5' cstyle %6 equiv %7").arg(oldName).arg(oldIndex).arg(i)
314
//                                         .arg(oldIndex>=0? m_Doc.paragraphStyle(oldName).parent() : "?").arg(coll->pstyles[i].parent())
315
//                                         .arg(oldIndex>=0? m_Doc.paragraphStyle(oldName).charStyle() == coll->pstyles[i].charStyle() : false)
316
//                                         .arg(oldIndex>=0? m_Doc.paragraphStyle(oldName).equiv(coll->pstyles[i]) : false));
317
 
318
                                if (oldIndex >= 0 && coll->pstyles[i] == m_Doc.paragraphStyle(oldName) )
319
                                        continue;
320
                                QString newName = oldName;
321
                                if (oldIndex >= 0 && !newNames.contains(oldName))
322
                                {
323
                                        int counter = 0;
324
                                        while (m_Doc.paragraphStyles().find(newName) >= 0)
325
                                                newName = (QObject::tr("Copy of %1 (%2)")).arg(oldName).arg(++counter);
326
                                        newNames[oldName] = newName;
327
                                }
328
                        }
329
                        coll->pstyles.rename(newNames);
8455 avox 330
                }
8879 avox 331
                while(newNames.count() > 0);
8455 avox 332
 
8879 avox 333
                m_Doc.redefineStyles(coll->pstyles, false);
334
 
9402 jghali 335
                //TODO: linestyles : this is temporary code until MultiLine is replaced by LineStyle
336
                QMap<QString,multiLine>::Iterator mlit;
337
                for (mlit = coll->lstyles.begin(); mlit != coll->lstyles.end(); ++mlit)
338
                {
339
                        multiLine& ml = mlit.data();
340
                        QString    oldName = mlit.key();
341
                        QString    newName = mlit.key();
342
                        QMap<QString,multiLine>::ConstIterator mlitd = m_Doc.MLineStyles.find(oldName);
343
                        if (mlitd != m_Doc.MLineStyles.end() && ml != mlitd.data())
344
                        {
345
                                int counter = 0;
346
                                while (m_Doc.MLineStyles.contains(newName))
347
                                        newName = (QObject::tr("Copy of %1 (%2)")).arg(oldName).arg(++counter);
348
                        }
349
                        m_Doc.MLineStyles.insert(newName, ml);
350
                }
8879 avox 351
 
8455 avox 352
                //TODO: patterns
353
 
354
                QPtrList<PageItem>* objects = &(coll->items);
355
 
356
//              qDebug(QString("deserialize: objects %1").arg((ulong)objects));
357
 
358
                for (uint i=0; i < objects->count(); ++i)
359
                {
360
//                      qDebug(QString("deserialized item: %1,%2").arg(objects->at(i)->xPos()).arg(objects->at(i)->yPos()));
361
                        PageItem* currItem = objects->at(i);
362
                        currItem->Clip = FlattenPath(currItem->PoLine, currItem->Segments);
363
                        result.addItem(currItem);
364
                }
365
//              qDebug(QString("deserialize: %1 objects, colors %2 %3").arg(objects->count()).arg((ulong)&(m_Doc.PageColors)).arg((ulong)&(coll->colors)));             
366
                m_Doc.PageColors.addColors(coll->colors, false);
367
//              qDebug(QString("deserialize: delete collection... %1").arg(result.count()));
9553 jghali 368
                updateGradientColors(coll->colors);
8455 avox 369
                delete coll;
8289 avox 370
        }
8455 avox 371
//      qDebug(QString("deserialize done: %1 items").arg(result.count()));
8289 avox 372
        return result;
8266 avox 373
}
374
 
375
 
8045 avox 376
bool Serializer::writeWithEncoding(const QString& filename, const QString& encoding,
377
                                                                   const QString& txt)
378
{
19 Franz 379
        QTextCodec *codec;
8045 avox 380
        if (encoding.isEmpty())
19 Franz 381
                codec = QTextCodec::codecForLocale();
382
        else
8045 avox 383
                codec = QTextCodec::codecForName(encoding);
384
        QCString dec = codec->fromUnicode( txt );
385
        QFile f(filename);
3 paul 386
        if (f.open(IO_WriteOnly))
167 Franz 387
        {
19 Franz 388
                f.writeBlock(dec, dec.length());
3 paul 389
                f.close();
8045 avox 390
                return true;
167 Franz 391
        }
8045 avox 392
        return false;
3 paul 393
}
394
 
8045 avox 395
 
396
bool Serializer::readWithEncoding(const QString& filename, const QString& encoding,
397
                                                                  QString &txt)
398
{
6013 jghali 399
        QCString file;
15 Franz 400
        QTextCodec *codec;
8045 avox 401
        if (encoding.isEmpty())
15 Franz 402
                codec = QTextCodec::codecForLocale();
403
        else
8045 avox 404
                codec = QTextCodec::codecForName(encoding);
405
        if (loadRawText(filename, file))
406
        {
407
                txt = codec->toUnicode( file.data() );
408
                return true;
409
        }
410
        return false;
3 paul 411
}
9553 jghali 412
 
413
void Serializer::updateGradientColors(const ColorList& colors)
414
{
415
        VColorStop* grStop;
416
        uint itemsCount = m_Doc.Items->count();
417
        for (uint c=0; c < itemsCount; ++c)
418
        {
419
                PageItem *ite = m_Doc.Items->at(c);
420
                QPtrVector<VColorStop> cstops = ite->fill_gradient.colorStops();
421
                for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
422
                {
423
                        grStop = cstops.at(cst);
424
                        if (colors.contains(grStop->name))
425
                                grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
426
                }
427
        }
428
        uint masterItemsCount =  m_Doc.MasterItems.count();
429
        for (uint c=0; c<masterItemsCount; ++c)
430
        {
431
                PageItem *ite = m_Doc.MasterItems.at(c);
432
                QPtrVector<VColorStop> cstops = ite->fill_gradient.colorStops();
433
                for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
434
                {
435
                        grStop = cstops.at(cst);
436
                        if (colors.contains(grStop->name))
437
                                grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
438
                }
439
        }
440
        uint frameItemsCount = m_Doc.FrameItems.count();
441
        for (uint c=0; c<frameItemsCount; ++c)
442
        {
443
                PageItem *ite = m_Doc.FrameItems.at(c);
444
                QPtrVector<VColorStop> cstops = ite->fill_gradient.colorStops();
445
                for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
446
                {
447
                        grStop = cstops.at(cst);
448
                        if (colors.contains(grStop->name))
449
                                grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
450
                }
451
        }
452
        QStringList patterns =m_Doc.docPatterns.keys();
453
        for (uint c = 0; c < patterns.count(); ++c)
454
        {
455
                ScPattern& pa = m_Doc.docPatterns[patterns[c]];
456
                for (uint o = 0; o < pa.items.count(); o++)
457
                {
458
                        PageItem *ite = pa.items.at(o);
459
                        QPtrVector<VColorStop> cstops = ite->fill_gradient.colorStops();
460
                        for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
461
                        {
462
                                grStop = cstops.at(cst);
463
                                if (colors.contains(grStop->name))
464
                                        grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
465
                        }
466
                }
467
        }
468
}