|
|
|
/* ****************************************************************************
|
|
|
|
This file is part of KBabel
|
|
|
|
|
|
|
|
Copyright (C) 1999-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
|
|
|
|
2002 by Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>
|
|
|
|
Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
In addition, as a special exception, the copyright holders give
|
|
|
|
permission to link the code of this program with any edition of
|
|
|
|
the TQt library by Trolltech AS, Norway (or with modified versions
|
|
|
|
of TQt that use the same license as TQt), and distribute linked
|
|
|
|
combinations including the two. You must obey the GNU General
|
|
|
|
Public License in all respects for all of the code used other than
|
|
|
|
TQt. If you modify this file, you may extend this exception to
|
|
|
|
your version of the file, but you are not obligated to do so. If
|
|
|
|
you do not wish to do so, delete this exception statement from
|
|
|
|
your version.
|
|
|
|
|
|
|
|
**************************************************************************** */
|
|
|
|
#include "catalogitem.h"
|
|
|
|
#include "catalogitem_private.h"
|
|
|
|
#include "editcmd.h"
|
|
|
|
#include "resources.h"
|
|
|
|
#include "libgettext/pofiles.h"
|
|
|
|
#include "libgettext/tokens.h"
|
|
|
|
|
|
|
|
#include "regexpextractor.h"
|
|
|
|
|
|
|
|
#include <textstream.h>
|
|
|
|
#include <textcodec.h>
|
|
|
|
#include <tqdom.h>
|
|
|
|
|
|
|
|
using namespace KBabel;
|
|
|
|
|
|
|
|
CatalogItem::CatalogItem(Project::Ptr project)
|
|
|
|
{
|
|
|
|
d=0;
|
|
|
|
clear();
|
|
|
|
d->_project = project;
|
|
|
|
}
|
|
|
|
|
|
|
|
CatalogItem::CatalogItem(const CatalogItem& item)
|
|
|
|
{
|
|
|
|
d=0;
|
|
|
|
clear();
|
|
|
|
*d=*(item.d);
|
|
|
|
}
|
|
|
|
|
|
|
|
CatalogItem::~CatalogItem()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString CatalogItem::comment() const
|
|
|
|
{
|
|
|
|
return d->_comment;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString CatalogItem::msgctxt(const bool noNewlines) const
|
|
|
|
{
|
|
|
|
if( noNewlines )
|
|
|
|
{
|
|
|
|
TQString tmp = d->_msgctxt;
|
|
|
|
tmp.replace("\n", " "); // ### TODO: " " or "" ?
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return d->_msgctxt;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList CatalogItem::msgid(const bool noNewlines) const
|
|
|
|
{
|
|
|
|
TQStringList result=d->_msgid;
|
|
|
|
if( noNewlines )
|
|
|
|
{
|
|
|
|
result.gres( "\n", "" );
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList CatalogItem::msgstr(const bool noNewlines) const
|
|
|
|
{
|
|
|
|
TQStringList result=d->_msgstr;
|
|
|
|
if( noNewlines )
|
|
|
|
{
|
|
|
|
result.gres( "\n", "" );
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList CatalogItem::msgstrAsList(int nr) const
|
|
|
|
{
|
|
|
|
TQString str;
|
|
|
|
if(d->_gettextPluralForm && nr > 0)
|
|
|
|
{
|
|
|
|
TQStringList::ConstIterator it = d->_msgstr.at(nr);
|
|
|
|
if(it != d->_msgstr.end())
|
|
|
|
{
|
|
|
|
str = *it;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kdDebug(KBABEL) << "request for non existing plural form "
|
|
|
|
<< nr << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
str = d->_msgstr.first();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList list=TQStringList::split("\n",str);
|
|
|
|
|
|
|
|
if(str.left(1)=="\n")
|
|
|
|
list.prepend("");
|
|
|
|
|
|
|
|
if(list.isEmpty())
|
|
|
|
list.append("");
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CatalogItem::isValid() const
|
|
|
|
{
|
|
|
|
return d->_valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::setMsgctxt(TQString msg)
|
|
|
|
{
|
|
|
|
d->_msgctxt=msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::setMsgid(TQString msg)
|
|
|
|
{
|
|
|
|
d->_msgid=msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::setMsgid(TQStringList msg)
|
|
|
|
{
|
|
|
|
d->_msgid=msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::setMsgstr(TQString msg)
|
|
|
|
{
|
|
|
|
d->_msgstr=msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::setMsgstr(TQStringList msg)
|
|
|
|
{
|
|
|
|
d->_msgstr=msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::setComment(TQString com)
|
|
|
|
{
|
|
|
|
d->_comment=com;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::setGettextPluralForm( bool _gettextPlural )
|
|
|
|
{
|
|
|
|
d->_gettextPluralForm = _gettextPlural;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList CatalogItem::errors() const
|
|
|
|
{
|
|
|
|
return d->_errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList CatalogItem::tagList( RegExpExtractor& te)
|
|
|
|
{
|
|
|
|
if(!d->_haveTagList)
|
|
|
|
{
|
|
|
|
// FIXME: should care about plural forms in msgid
|
|
|
|
te.setString(msgid(true).first());
|
|
|
|
d->_tagList = TQStringList(te.matches());
|
|
|
|
d->_haveTagList = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return d->_tagList;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList CatalogItem::argList( RegExpExtractor& te)
|
|
|
|
{
|
|
|
|
if(!d->_haveArgList)
|
|
|
|
{
|
|
|
|
// FIXME: should care about plural forms in msgid
|
|
|
|
te.setString(msgid(true).first());
|
|
|
|
d->_argList = TQStringList(te.matches());
|
|
|
|
}
|
|
|
|
|
|
|
|
return d->_argList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CatalogItem::isFuzzy() const
|
|
|
|
{
|
|
|
|
return d->_comment.find( TQRegExp(",\\s*fuzzy") ) != -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CatalogItem::isCformat() const
|
|
|
|
{
|
|
|
|
// Allow "possible-c-format" (from xgettext --debug) or "c-format"
|
|
|
|
// Note the regexp (?: ) is similar to () but it does not capture (so it is faster)
|
|
|
|
return d->_comment.find( TQRegExp(",\\s*(?:possible-)c-format") ) == -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CatalogItem::isNoCformat() const
|
|
|
|
{
|
|
|
|
return d->_comment.find( TQRegExp(",\\s*no-c-format") ) == -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CatalogItem::isTQtformat() const
|
|
|
|
{
|
|
|
|
return d->_comment.find( TQRegExp(",\\s*qt-format") ) == -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CatalogItem::isNoTQtformat() const
|
|
|
|
{
|
|
|
|
return d->_comment.find( TQRegExp(",\\s*no-qt-format") ) == -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CatalogItem::isUntranslated() const
|
|
|
|
{
|
|
|
|
return d->_msgstr.first().isEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
PluralFormType CatalogItem::pluralForm() const
|
|
|
|
{
|
|
|
|
if( d->_gettextPluralForm )
|
|
|
|
return Gettext;
|
|
|
|
if( d->_msgid.first().startsWith( "_n: " ) )
|
|
|
|
return KDESpecific;
|
|
|
|
else
|
|
|
|
return NoPluralForm;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CatalogItem::totalLines() const
|
|
|
|
{
|
|
|
|
int lines=0;
|
|
|
|
if(!d->_comment.isEmpty())
|
|
|
|
{
|
|
|
|
lines = d->_comment.contains('\n')+1;
|
|
|
|
}
|
|
|
|
int msgctxtLines=0;
|
|
|
|
if(!d->_msgctxt.isEmpty())
|
|
|
|
{
|
|
|
|
msgctxtLines=d->_msgctxt.contains('\n')+1;
|
|
|
|
}
|
|
|
|
int msgidLines=0;
|
|
|
|
TQStringList::ConstIterator it;
|
|
|
|
for(it=d->_msgid.begin(); it != d->_msgid.end(); ++it)
|
|
|
|
{
|
|
|
|
msgidLines += (*it).contains('\n')+1;
|
|
|
|
}
|
|
|
|
int msgstrLines=0;
|
|
|
|
for(it=d->_msgstr.begin(); it != d->_msgstr.end(); ++it)
|
|
|
|
{
|
|
|
|
msgstrLines += (*it).contains('\n')+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(msgctxtLines>1)
|
|
|
|
msgctxtLines++;
|
|
|
|
if(msgidLines>1)
|
|
|
|
msgidLines++;
|
|
|
|
if(msgstrLines>1)
|
|
|
|
msgstrLines++;
|
|
|
|
|
|
|
|
lines+=( msgctxtLines+msgidLines+msgstrLines );
|
|
|
|
|
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CatalogItem::setSyntaxError(bool on)
|
|
|
|
{
|
|
|
|
if(on && !d->_errors.contains("syntax error"))
|
|
|
|
d->_errors.append("syntax error");
|
|
|
|
else
|
|
|
|
d->_errors.remove("syntax error");
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPtrList<EditCommand> CatalogItem::removeFuzzy(bool doIt)
|
|
|
|
{
|
|
|
|
TQPtrList<EditCommand> editList;
|
|
|
|
editList.setAutoDelete(false);
|
|
|
|
|
|
|
|
TQString comment=d->_comment;
|
|
|
|
|
|
|
|
if(isFuzzy())
|
|
|
|
{
|
|
|
|
EditCommand *cmd;
|
|
|
|
TQRegExp fuzzyStr(",\\s*fuzzy");
|
|
|
|
|
|
|
|
int offset;
|
|
|
|
offset=comment.find(fuzzyStr);
|
|
|
|
while(offset>=0)
|
|
|
|
{
|
|
|
|
cmd = new DelTextCmd(offset,fuzzyStr.cap(),0);
|
|
|
|
cmd->setPart(Comment);
|
|
|
|
editList.append(cmd);
|
|
|
|
|
|
|
|
comment.remove(offset,fuzzyStr.cap().length());
|
|
|
|
|
|
|
|
offset=comment.find(fuzzyStr,offset+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove empty comment lines
|
|
|
|
if( comment.contains( TQRegExp("^#\\s*$") ))
|
|
|
|
{
|
|
|
|
cmd = new DelTextCmd(0,comment,0);
|
|
|
|
cmd->setPart(Comment);
|
|
|
|
editList.append(cmd);
|
|
|
|
|
|
|
|
comment="";
|
|
|
|
}
|
|
|
|
if( comment.contains( TQRegExp("\n#\\s*$") ))
|
|
|
|
{
|
|
|
|
offset=comment.find( TQRegExp("\n#\\s*$") );
|
|
|
|
while(offset>=0)
|
|
|
|
{
|
|
|
|
cmd = new DelTextCmd(offset,comment.mid(offset),0);
|
|
|
|
cmd->setPart(Comment);
|
|
|
|
editList.append(cmd);
|
|
|
|
|
|
|
|
comment.remove(offset,comment.length()-offset);
|
|
|
|
|
|
|
|
offset=comment.find( TQRegExp("\n#\\s*$"), offset+1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( comment.contains( TQRegExp("\n#\\s*\n") ))
|
|
|
|
{
|
|
|
|
offset=comment.find( TQRegExp("\n#\\s*\n") )+1;
|
|
|
|
while(offset>=0)
|
|
|
|
{
|
|
|
|
int endIndex=comment.find("\n",offset)+1;
|
|
|
|
|
|
|
|
cmd = new DelTextCmd(offset,comment.mid(offset,endIndex-offset),0);
|
|
|
|
cmd->setPart(Comment);
|
|
|
|
editList.append(cmd);
|
|
|
|
|
|
|
|
comment.remove(offset,endIndex-offset);
|
|
|
|
|
|
|
|
offset=comment.find( TQRegExp("\n#\\s*\n"), offset+1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(doIt)
|
|
|
|
d->_comment=comment;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return editList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQPtrList<EditCommand> CatalogItem::addFuzzy(bool doIt)
|
|
|
|
{
|
|
|
|
TQPtrList<EditCommand> editList;
|
|
|
|
editList.setAutoDelete(false);
|
|
|
|
|
|
|
|
|
|
|
|
if(!isFuzzy())
|
|
|
|
{
|
|
|
|
EditCommand *cmd;
|
|
|
|
int offset=d->_comment.length();
|
|
|
|
|
|
|
|
TQString addStr;
|
|
|
|
if(offset > 0 && d->_comment[offset-1] != '\n')
|
|
|
|
{
|
|
|
|
addStr='\n';
|
|
|
|
}
|
|
|
|
addStr+="#, fuzzy";
|
|
|
|
|
|
|
|
cmd = new InsTextCmd(offset,addStr,0);
|
|
|
|
cmd->setPart(Comment);
|
|
|
|
editList.append(cmd);
|
|
|
|
|
|
|
|
|
|
|
|
if(doIt)
|
|
|
|
d->_comment+=addStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return editList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CatalogItem::processCommand(EditCommand* cmd, bool undo)
|
|
|
|
{
|
|
|
|
kdDebug(KBABEL) << "CatalogItem::processCommand" << endl;
|
|
|
|
if(cmd->terminator()!=0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DelTextCmd* delcmd = (DelTextCmd*) cmd;
|
|
|
|
|
|
|
|
bool ins = true;
|
|
|
|
if (delcmd->type() == EditCommand::Delete )
|
|
|
|
ins = undo;
|
|
|
|
else if (delcmd->type() == EditCommand::Insert )
|
|
|
|
ins = !undo;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kdDebug(KBABEL) << "what kind of edit command is this?" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ins )
|
|
|
|
{
|
|
|
|
if(delcmd->part()==Msgstr)
|
|
|
|
{
|
|
|
|
if(delcmd->pluralNumber >= (int)d->_msgstr.count() )
|
|
|
|
{
|
|
|
|
for( uint i = d->_msgstr.count() ; i < (uint)(delcmd->pluralNumber+1) ; i++ )
|
|
|
|
d->_msgstr.append( "" );
|
|
|
|
}
|
|
|
|
|
|
|
|
(*(d->_msgstr).at(delcmd->pluralNumber)).insert(delcmd->offset,delcmd->str);
|
|
|
|
}
|
|
|
|
else if(delcmd->part()==Comment)
|
|
|
|
{
|
|
|
|
d->_comment.insert(delcmd->offset,delcmd->str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // del
|
|
|
|
if(delcmd->part()==Msgstr)
|
|
|
|
{
|
|
|
|
if(delcmd->pluralNumber >= (int)d->_msgstr.count() )
|
|
|
|
{
|
|
|
|
for( uint i = d->_msgstr.count() ; i < (uint)(delcmd->pluralNumber+1) ; i++ )
|
|
|
|
d->_msgstr.append( "" );
|
|
|
|
}
|
|
|
|
|
|
|
|
(*(d->_msgstr).at(delcmd->pluralNumber)).remove(delcmd->offset,delcmd->str.length());
|
|
|
|
}
|
|
|
|
else if(delcmd->part()==Comment)
|
|
|
|
{
|
|
|
|
d->_comment.remove(delcmd->offset,delcmd->str.length());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CatalogItem::clear()
|
|
|
|
{
|
|
|
|
if( !d ) d = new CatalogItemPrivate();
|
|
|
|
else {
|
|
|
|
d->_msgid.clear();
|
|
|
|
d->_msgstr.clear();
|
|
|
|
d->_errors.clear();
|
|
|
|
|
|
|
|
d->_tagList.clear();
|
|
|
|
d->_argList.clear();
|
|
|
|
}
|
|
|
|
d->_comment="";
|
|
|
|
d->_msgctxt="";
|
|
|
|
d->_valid=true;
|
|
|
|
d->_gettextPluralForm=false;
|
|
|
|
d->_haveTagList=false;
|
|
|
|
d->_haveArgList=false;
|
|
|
|
|
|
|
|
d->_msgid.append("");
|
|
|
|
d->_msgstr.append("");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::operator=(const CatalogItem& rhs)
|
|
|
|
{
|
|
|
|
d->_comment = rhs.d->_comment;
|
|
|
|
d->_msgctxt = rhs.d->_msgctxt;
|
|
|
|
d->_msgid = rhs.d->_msgid;
|
|
|
|
d->_msgstr = rhs.d->_msgstr;
|
|
|
|
d->_valid = rhs.d->_valid;
|
|
|
|
d->_errors = rhs.d->_errors;
|
|
|
|
d->_gettextPluralForm = rhs.d->_gettextPluralForm;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString CatalogItem::nextError() const
|
|
|
|
{
|
|
|
|
return d->_errors.first();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::clearErrors()
|
|
|
|
{
|
|
|
|
d->_errors.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::appendError(const TQString& error )
|
|
|
|
{
|
|
|
|
if( !d->_errors.contains( error ) )
|
|
|
|
d->_errors.append(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::removeError(const TQString& error )
|
|
|
|
{
|
|
|
|
d->_errors.remove(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
Project::Ptr CatalogItem::project() const
|
|
|
|
{
|
|
|
|
return d->_project;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CatalogItem::setProject( Project::Ptr project )
|
|
|
|
{
|
|
|
|
d->_project = project;
|
|
|
|
}
|
|
|
|
|
|
|
|
// kate: space-indent on; indent-width 4; replace-tabs on;
|