• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

lokalize

  • sources
  • kde-4.12
  • kdesdk
  • lokalize
  • src
  • catalog
  • ts
tsstorage.cpp
Go to the documentation of this file.
1 /*
2 Copyright 2008-2012 Nick Shaforostoff <shaforostoff@kde.ru>
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of
7 the License or (at your option) version 3 or any later version
8 accepted by the membership of KDE e.V. (or its successor approved
9 by the membership of KDE e.V.), which shall act as a proxy
10 defined in Section 14 of version 3 of the license.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "tsstorage.h"
22 
23 #include "gettextheader.h"
24 #include "project.h"
25 #include "version.h"
26 #include "prefs_lokalize.h"
27 
28 #include <QProcess>
29 #include <QString>
30 #include <QMap>
31 #include <QDomDocument>
32 #include <QTime>
33 #include <QPair>
34 #include <QList>
35 
36 
37 #include <kdebug.h>
38 #include <kglobal.h>
39 #include <klocale.h>
40 #include <kdatetime.h>
41 #include <QXmlSimpleReader>
42 
43 static const char* const noyes[]={"no","yes"};
44 
45 static const QString names[]={"source" ,"translation","oldsource" ,"translatorcomment","comment" ,"name" ,"numerus"};
46 enum TagNames {SourceTag,TargetTag ,OldSourceTag,NoteTag ,DevNoteTag,NameTag,PluralTag};
47 
48 static const QString attrnames[]={"location" ,"type" ,"obsolete"};
49 enum AttrNames {LocationAttr,TypeAttr,ObsoleteAttr};
50 
51 static const QString attrvalues[]={"obsolete"};
52 enum AttValues {ObsoleteVal};
53 
54 TsStorage::TsStorage()
55  : CatalogStorage()
56 {
57 }
58 
59 TsStorage::~TsStorage()
60 {
61 }
62 
63 int TsStorage::capabilities() const
64 {
65  return 0;//MultipleNotes;
66 }
67 
68 //BEGIN OPEN/SAVE
69 
70 int TsStorage::load(QIODevice* device)
71 {
72  QTime chrono;chrono.start();
73 
74 
75  QXmlSimpleReader reader;
76  reader.setFeature("http://qtsoftware.com/xml/features/report-whitespace-only-CharData",true);
77  reader.setFeature("http://xml.org/sax/features/namespaces",false);
78  QXmlInputSource source(device);
79 
80  QString errorMsg;
81  int errorLine;//+errorColumn;
82  bool success=m_doc.setContent(&source, &reader, &errorMsg, &errorLine/*,errorColumn*/);
83 
84  if (!success)
85  {
86  kWarning()<<errorMsg;
87  return errorLine+1;
88  }
89 
90 
91  QDomElement file=m_doc.elementsByTagName("TS").at(0).toElement();
92  m_sourceLangCode=file.attribute("sourcelanguage");
93  m_targetLangCode=file.attribute("language");
94  m_numberOfPluralForms=numberOfPluralFormsForLangCode(m_targetLangCode);
95 
96  //Create entry mapping.
97  //Along the way: for langs with more than 2 forms
98  //we create any form-entries additionally needed
99 
100  entries=m_doc.elementsByTagName("message");
101  int size=entries.size();
102 
103  kWarning()<<chrono.elapsed();
104  return 0;
105 }
106 
107 bool TsStorage::save(QIODevice* device, bool belongsToProject)
108 {
109  QTextStream stream(device);
110  m_doc.save(stream,4);
111  return true;
112 }
113 //END OPEN/SAVE
114 
115 //BEGIN STORAGE TRANSLATION
116 
117 int TsStorage::size() const
118 {
119  //return m_map.size();
120 
121  return entries.size();
122 }
123 
124 
125 
126 
130 struct ContentEditingData
131 {
132  enum ActionType{Get,DeleteText,InsertText,CheckLength};
133 
134  QString stringToInsert;
135  int pos;
136  int lengthOfStringToRemove;
137  ActionType actionType;
138 
140  ContentEditingData(ActionType type=Get)
141  : pos(-1)
142  , lengthOfStringToRemove(-1)
143  , actionType(type)
144  {}
145 
147  ContentEditingData(int p, int l)
148  : pos(p)
149  , lengthOfStringToRemove(l)
150  , actionType(DeleteText)
151  {}
152 
154  ContentEditingData(int p,const QString& s)
155  : stringToInsert(s)
156  , pos(p)
157  , lengthOfStringToRemove(-1)
158  , actionType(InsertText)
159  {}
160 };
161 
162 static QString doContent(QDomElement elem, int startingPos, ContentEditingData* data);
163 
170 static QString content(QDomElement elem, ContentEditingData* data=0)
171 {
172  return doContent(elem, 0, data);
173 }
174 
175 static QString doContent(QDomElement elem, int startingPos, ContentEditingData* data)
176 {
177  //actually startingPos is current pos
178 
179  QString result;
180 
181  if (elem.isNull()
182  || (!result.isEmpty() && ContentEditingData::CheckLength))
183  return QString();
184 
185  bool seenCharacterDataAfterElement=false;
186 
187  QDomNode n = elem.firstChild();
188  while (!n.isNull())
189  {
190  if (n.isCharacterData())
191  {
192  seenCharacterDataAfterElement=true;
193 
194  QDomCharacterData c=n.toCharacterData();
195  QString cData=c.data();
196 
197  if (data && data->pos!=-1 &&
198  data->pos>=startingPos && data->pos<=startingPos+cData.size())
199  {
200  // time to do some action! ;)
201  int localStartPos=data->pos-startingPos;
202 
203  //BEGIN DELETE TEXT
204  if (data->actionType==ContentEditingData::DeleteText) //(data->lengthOfStringToRemove!=-1)
205  {
206  if (localStartPos+data->lengthOfStringToRemove>cData.size())
207  {
208  //text is fragmented into several QDomCharacterData
209  int localDelLen=cData.size()-localStartPos;
210  //qWarning()<<"text is fragmented into several QDomCharacterData. localDelLen:"<<localDelLen<<"cData:"<<cData;
211  c.deleteData(localStartPos,localDelLen);
212  //setup data for future iterations
213  data->lengthOfStringToRemove=data->lengthOfStringToRemove-localDelLen;
214  //data->pos=startingPos;
215  //qWarning()<<"\tsetup:"<<data->pos<<data->lengthOfStringToRemove;
216  }
217  else
218  {
219  //qWarning()<<"simple delete"<<localStartPos<<data->lengthOfStringToRemove;
220  c.deleteData(localStartPos,data->lengthOfStringToRemove);
221  data->actionType=ContentEditingData::CheckLength;
222  return QString('a');//so it exits 100%
223  }
224  }
225  //END DELETE TEXT
226  //INSERT
227  else if (data->actionType==ContentEditingData::InsertText)
228  {
229  c.insertData(localStartPos,data->stringToInsert);
230  data->actionType=ContentEditingData::CheckLength;
231  return QString('a');//so it exits 100%
232  }
233  cData=c.data();
234  }
235  //else
236  // if (data&&data->pos!=-1/*&& n.nextSibling().isNull()*/)
237  // kWarning()<<"arg!"<<startingPos<<"data->pos"<<data->pos;
238 
239  result += cData;
240  startingPos+=cData.size();
241  }
242  n = n.nextSibling();
243  }
244  if (!seenCharacterDataAfterElement)
245  {
246  //add empty charData child so that user could add some text
247  elem.appendChild( elem.ownerDocument().createTextNode(QString()) );
248  }
249 
250  return result;
251 }
252 
253 
254 
255 //flat-model interface (ignores XLIFF grouping)
256 
257 CatalogString TsStorage::catalogString(QDomElement contentElement) const
258 {
259  CatalogString catalogString;
260  ContentEditingData data(ContentEditingData::Get);
261  catalogString.string=content(contentElement, &data);
262  return catalogString;
263 }
264 
265 CatalogString TsStorage::catalogString(const DocPosition& pos) const
266 {
267  return catalogString(pos.part==DocPosition::Target?targetForPos(pos):sourceForPos(pos.entry));
268 }
269 
270 CatalogString TsStorage::targetWithTags(DocPosition pos) const
271 {
272  return catalogString(targetForPos(pos));
273 }
274 CatalogString TsStorage::sourceWithTags(DocPosition pos) const
275 {
276  return catalogString(sourceForPos(pos.entry));
277 }
278 
279 QString TsStorage::source(const DocPosition& pos) const
280 {
281  return content(sourceForPos(pos.entry));
282 }
283 QString TsStorage::target(const DocPosition& pos) const
284 {
285  return content(targetForPos(pos));
286 }
287 
288 
289 void TsStorage::targetDelete(const DocPosition& pos, int count)
290 {
291  ContentEditingData data(pos.offset,count);
292  content(targetForPos(pos),&data);
293 }
294 
295 void TsStorage::targetInsert(const DocPosition& pos, const QString& arg)
296 {
297  kWarning()<<pos.entry<<arg;
298  QDomElement targetEl=targetForPos(pos);
299  //BEGIN add <*target>
300  if (targetEl.isNull())
301  {
302  QDomNode unitEl=unitForPos(pos.entry);
303  QDomNode refNode=unitEl.firstChildElement(names[SourceTag]);
304  targetEl = unitEl.insertAfter(m_doc.createElement(names[TargetTag]),refNode).toElement();
305 
306  if (pos.entry<size())
307  {
308  targetEl.appendChild(m_doc.createTextNode(arg));//i bet that pos.offset is 0 ;)
309  return;
310  }
311  }
312  //END add <*target>
313  if (arg.isEmpty()) return; //means we were called just to add <taget> tag
314 
315  ContentEditingData data(pos.offset,arg);
316  content(targetEl,&data);
317 }
318 
319 void TsStorage::setTarget(const DocPosition& pos, const QString& arg)
320 {
321  Q_UNUSED(pos);
322  Q_UNUSED(arg);
323 //TODO
324 }
325 
326 
327 QVector<AltTrans> TsStorage::altTrans(const DocPosition& pos) const
328 {
329  QVector<AltTrans> result;
330 
331  QString oldsource=content(unitForPos(pos.entry).firstChildElement(names[OldSourceTag]));
332  if (!oldsource.isEmpty())
333  result<<AltTrans(CatalogString(oldsource), i18n("Previous source value, saved by lupdate tool"));
334 
335  return result;
336 }
337 
338 
339 QStringList TsStorage::sourceFiles(const DocPosition& pos) const
340 {
341  QStringList result;
342 
343  QDomElement elem = unitForPos(pos.entry).firstChildElement(attrnames[LocationAttr]);
344  while (!elem.isNull())
345  {
346  QString sourcefile=elem.attribute("filename");
347  QString linenumber=elem.attribute("line");
348  if (!( sourcefile.isEmpty()&&linenumber.isEmpty() ))
349  result.append(sourcefile+':'+linenumber);
350 
351  elem=elem.nextSiblingElement(attrnames[LocationAttr]);
352  }
353  //qSort(result);
354 
355  return result;
356 }
357 
358 QVector<Note> TsStorage::notes(const DocPosition& pos) const
359 {
360  QVector<Note> result;
361 
362  QDomElement elem = unitForPos(pos.entry).firstChildElement(names[NoteTag]);
363  while (!elem.isNull())
364  {
365  Note note;
366  note.content=elem.text();
367  result.append(note);
368 
369  elem=elem.nextSiblingElement(names[NoteTag]);
370  }
371  return result;
372 }
373 
374 QVector<Note> TsStorage::developerNotes(const DocPosition& pos) const
375 {
376  QVector<Note> result;
377 
378  QDomElement elem = unitForPos(pos.entry).firstChildElement(names[DevNoteTag]);
379  while (!elem.isNull())
380  {
381  Note note;
382  note.content=elem.text();
383  result.append(note);
384 
385  elem=elem.nextSiblingElement(names[DevNoteTag]);
386  }
387  return result;
388 }
389 
390 Note TsStorage::setNote(DocPosition pos, const Note& note)
391 {
392  //kWarning()<<int(pos.form)<<note.content;
393  QDomElement unit=unitForPos(pos.entry);
394  QDomElement elem;
395  Note oldNote;
396  if (pos.form==-1 && !note.content.isEmpty())
397  {
398  QDomElement ref=unit.lastChildElement(names[NoteTag]);
399  elem=unit.insertAfter( m_doc.createElement(names[NoteTag]),ref).toElement();
400  elem.appendChild(m_doc.createTextNode(QString()));
401  }
402  else
403  {
404  QDomNodeList list=unit.elementsByTagName(names[NoteTag]);
405  if (pos.form==-1) pos.form=list.size()-1;
406  if (pos.form<list.size())
407  {
408  elem = unit.elementsByTagName(names[NoteTag]).at(pos.form).toElement();
409  oldNote.content=elem.text();
410  }
411  }
412 
413  if (elem.isNull()) return oldNote;
414 
415  if (!elem.text().isEmpty())
416  {
417  ContentEditingData data(0,elem.text().size());
418  content(elem,&data);
419  }
420 
421  if (!note.content.isEmpty())
422  {
423  ContentEditingData data(0,note.content);
424  content(elem,&data);
425  }
426  else
427  unit.removeChild(elem);
428 
429  return oldNote;
430 }
431 
432 QStringList TsStorage::context(const DocPosition& pos) const
433 {
434  QStringList result;
435 
436  QDomElement unit=unitForPos(pos.entry);
437  QDomElement context=unit.parentNode().toElement();
438  //if (context.isNull())
439  // return result;
440 
441  QDomElement name=context.firstChildElement(names[NameTag]);
442  if (name.isNull())
443  return result;
444 
445  result.append(name.text());
446  return result;
447 }
448 
449 QStringList TsStorage::matchData(const DocPosition& pos) const
450 {
451  Q_UNUSED(pos);
452  return QStringList();
453 }
454 
455 QString TsStorage::id(const DocPosition& pos) const
456 {
457  QString result=source(pos);
458  result.remove('\n');
459  QStringList ctxt=context(pos);
460  if (ctxt.size())
461  result.prepend(ctxt.first());
462  return result;
463 }
464 
465 bool TsStorage::isPlural(const DocPosition& pos) const
466 {
467  QDomElement unit=unitForPos(pos.entry);
468 
469  return unit.hasAttribute(names[PluralTag]);
470 }
471 
472 void TsStorage::setApproved(const DocPosition& pos, bool approved)
473 {
474  targetInsert(pos,QString()); //adds <taget> if needed
475  QDomElement target=unitForPos(pos.entry).firstChildElement(names[TargetTag]); //asking directly to bypass plural state detection
476  if (target.attribute(attrnames[TypeAttr])==attrvalues[ObsoleteVal])
477  return;
478  if (approved)
479  target.removeAttribute(attrnames[TypeAttr]);
480  else
481  target.setAttribute(attrnames[TypeAttr],"unfinished");
482 }
483 
484 bool TsStorage::isApproved(const DocPosition& pos) const
485 {
486  QDomElement target=unitForPos(pos.entry).firstChildElement(names[TargetTag]);
487  return !target.hasAttribute(attrnames[TypeAttr]);
488 }
489 
490 bool TsStorage::isObsolete(int entry) const
491 {
492  QDomElement target=unitForPos(entry).firstChildElement(names[TargetTag]);
493  return target.attribute(attrnames[TypeAttr])==attrvalues[ObsoleteVal];
494 }
495 
496 bool TsStorage::isEmpty(const DocPosition& pos) const
497 {
498  ContentEditingData data(ContentEditingData::CheckLength);
499  return content(targetForPos(pos),&data).isEmpty();
500 }
501 
502 bool TsStorage::isEquivTrans(const DocPosition& pos) const
503 {
504  return true;//targetForPos(pos.entry).attribute("equiv-trans")!="no";
505 }
506 
507 void TsStorage::setEquivTrans(const DocPosition& pos, bool equivTrans)
508 {
509  //targetForPos(pos.entry).setAttribute("equiv-trans",noyes[equivTrans]);
510 }
511 
512 QDomElement TsStorage::unitForPos(int pos) const
513 {
514  return entries.at(pos).toElement();
515 }
516 
517 QDomElement TsStorage::targetForPos(DocPosition pos) const
518 {
519  QDomElement unit=unitForPos(pos.entry);
520  QDomElement translation=unit.firstChildElement(names[TargetTag]);
521  if (!unit.hasAttribute(names[PluralTag]))
522  return translation;
523 
524  if (pos.form==-1) pos.form=0;
525 
526  QDomNodeList forms=translation.elementsByTagName("numerusform");
527  while (pos.form>=forms.size())
528  translation.appendChild( unit.ownerDocument().createElement("numerusform") );
529  return forms.at(pos.form).toElement();
530 }
531 
532 QDomElement TsStorage::sourceForPos(int pos) const
533 {
534  return unitForPos(pos).firstChildElement(names[SourceTag]);
535 }
536 
537 //END STORAGE TRANSLATION
538 
539 
noyes
static const char *const noyes[]
Definition: tsstorage.cpp:43
DocPosition::part
Part part
Definition: pos.h:49
project.h
TsStorage::load
int load(QIODevice *device)
Definition: tsstorage.cpp:70
TsStorage::sourceFiles
QStringList sourceFiles(const DocPosition &pos) const
Definition: tsstorage.cpp:339
TargetTag
Definition: tsstorage.cpp:46
DocPosition::Target
Definition: pos.h:44
AttValues
AttValues
Definition: tsstorage.cpp:52
TsStorage::~TsStorage
~TsStorage()
Definition: tsstorage.cpp:59
ObsoleteVal
Definition: tsstorage.cpp:52
PluralTag
Definition: tsstorage.cpp:46
Note
Definition: note.h:29
TsStorage::setApproved
void setApproved(const DocPosition &pos, bool approved)
Definition: tsstorage.cpp:472
TsStorage::matchData
QStringList matchData(const DocPosition &pos) const
user-invisible data for matching, e.g.
Definition: tsstorage.cpp:449
CatalogStorage::m_numberOfPluralForms
int m_numberOfPluralForms
Definition: catalogstorage.h:156
CatalogString::string
QString string
Definition: catalogstring.h:130
tsstorage.h
attrvalues
static const QString attrvalues[]
Definition: tsstorage.cpp:51
TsStorage::isEmpty
bool isEmpty() const
DocPosition::offset
uint offset
Definition: pos.h:51
DocPosition::entry
int entry
Definition: pos.h:48
DocPosition
This struct represents a position in a catalog.
Definition: pos.h:38
TsStorage::isApproved
bool isApproved(const DocPosition &pos) const
Definition: tsstorage.cpp:484
TsStorage::save
bool save(QIODevice *device, bool belongsToProject=false)
Definition: tsstorage.cpp:107
TsStorage::notes
QVector< Note > notes(const DocPosition &pos) const
Definition: tsstorage.cpp:358
TsStorage::isEquivTrans
bool isEquivTrans(const DocPosition &pos) const
Definition: tsstorage.cpp:502
content
static QString content(QDomElement elem, ContentEditingData *data=0)
walks through XLIFF XML and performs actions depending on ContentEditingData:
Definition: tsstorage.cpp:170
TsStorage::isObsolete
bool isObsolete(int entry) const
Definition: tsstorage.cpp:490
TsStorage::source
QString source(const DocPosition &pos) const
flat-model interface (ignores XLIFF grouping)
Definition: tsstorage.cpp:279
DocPosition::form
char form
Definition: pos.h:50
TypeAttr
Definition: tsstorage.cpp:49
TsStorage::isPlural
bool isPlural(const DocPosition &pos) const
Definition: tsstorage.cpp:465
gettextheader.h
CatalogStorage::m_targetLangCode
QString m_targetLangCode
Definition: catalogstorage.h:154
OldSourceTag
Definition: tsstorage.cpp:46
NameTag
Definition: tsstorage.cpp:46
TsStorage::target
QString target(const DocPosition &pos) const
Definition: tsstorage.cpp:283
TsStorage::targetWithTags
CatalogString targetWithTags(DocPosition pos) const
Definition: tsstorage.cpp:270
ObsoleteAttr
Definition: tsstorage.cpp:49
CatalogStorage
Abstract interface for storage of translation file.
Definition: catalogstorage.h:45
TsStorage::catalogString
CatalogString catalogString(const DocPosition &pos) const
Definition: tsstorage.cpp:265
names
static const QString names[]
Definition: tsstorage.cpp:45
attrnames
static const QString attrnames[]
Definition: tsstorage.cpp:48
SourceTag
Definition: tsstorage.cpp:46
TsStorage::TsStorage
TsStorage()
Definition: tsstorage.cpp:54
TsStorage::setNote
Note setNote(DocPosition pos, const Note &note)
pos.form is note number
Definition: tsstorage.cpp:390
TsStorage::setEquivTrans
void setEquivTrans(const DocPosition &pos, bool equivTrans)
Definition: tsstorage.cpp:507
version.h
Note::content
QString content
Definition: note.h:33
CatalogString
data structure used to pass info about inline elements a XLIFF tag is represented by a TAGRANGE_IMAGE...
Definition: catalogstring.h:128
TsStorage::capabilities
int capabilities() const
Definition: tsstorage.cpp:63
TsStorage::size
int size() const
Definition: tsstorage.cpp:117
prefs_lokalize.h
AttrNames
AttrNames
Definition: tsstorage.cpp:49
TsStorage::context
QStringList context(const DocPosition &pos) const
Definition: tsstorage.cpp:432
DevNoteTag
Definition: tsstorage.cpp:46
TsStorage::developerNotes
QVector< Note > developerNotes(const DocPosition &pos) const
Definition: tsstorage.cpp:374
CatalogStorage::m_sourceLangCode
QString m_sourceLangCode
Definition: catalogstorage.h:153
TsStorage::targetInsert
void targetInsert(const DocPosition &pos, const QString &arg)
Definition: tsstorage.cpp:295
doContent
static QString doContent(QDomElement elem, int startingPos, ContentEditingData *data)
Definition: tsstorage.cpp:175
TsStorage::setTarget
void setTarget(const DocPosition &pos, const QString &arg)
Definition: tsstorage.cpp:319
TsStorage::sourceWithTags
CatalogString sourceWithTags(DocPosition pos) const
Definition: tsstorage.cpp:274
TsStorage::id
QString id(const DocPosition &pos) const
entry id unique for this file
Definition: tsstorage.cpp:455
LocationAttr
Definition: tsstorage.cpp:49
TsStorage::altTrans
QVector< AltTrans > altTrans(const DocPosition &pos) const
Definition: tsstorage.cpp:327
AltTrans
Definition: alttrans.h:30
TagNames
TagNames
Definition: tsstorage.cpp:46
numberOfPluralFormsForLangCode
int numberOfPluralFormsForLangCode(const QString &langCode)
Definition: gettextheader.cpp:149
NoteTag
Definition: tsstorage.cpp:46
TsStorage::targetDelete
void targetDelete(const DocPosition &pos, int count)
edit operations used by undo/redo system and sync-mode
Definition: tsstorage.cpp:289
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:03:45 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

lokalize

Skip menu "lokalize"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • okteta
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal