You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/kbabel/catalogmanager/catmanlistitem.cpp

933 lines
22 KiB

/* ****************************************************************************
This file is part of KBabel
Copyright (C) 1999-2000 by Matthias Kiefer
<matthias.kiefer@gmx.de>
2001-2003 by Stanislav Visnovsky
<visnovsky@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 "catmanresource.h"
#include "catmanlistitem.h"
#include "catalogmanagerview.h"
#include "catalog.h"
#include "resources.h"
#include <klocale.h>
#include <tqfileinfo.h>
#include <tqdir.h>
#include <tqbitmap.h>
#include <tqlabel.h>
#include <tqpainter.h>
#include <cvshandler.h>
#include <svnhandler.h>
using namespace KBabel;
CatManListItem::CatManListItem(CatalogManagerView *view, TQListViewItem* parent,TQString fullPath,TQString fullPotPath,TQString package)
: TQListViewItem(parent)
{
_view = view;
init(fullPath,fullPotPath,package);
}
CatManListItem::CatManListItem(CatalogManagerView *view, TQListView* parent,TQString fullPath,TQString fullPotPath)
: TQListViewItem(parent)
{
_primary=TQFileInfo(fullPath);
_template=TQFileInfo(fullPotPath);
_package="/";
_type=Dir;
_marked=false;
_view = view;
_hasPo=false;
_hasPot=false;
_hasErrors=false;
_primary.setCaching(false);
_template.setCaching(false);
setText(COL_NAME,i18n("Message Catalogs"));
setPixmap(COL_NAME,ICON_FOLDER_CLOSED_OK);
}
void CatManListItem::init(const TQString& fullPath, const TQString& fullPotPath, const TQString& package)
{
_primary=TQFileInfo(fullPath);
_template=TQFileInfo(fullPotPath);
_package=package;
_marked=false;
_hasPo=false;
_hasPot=false;
_hasErrors=false;
_primary.setCaching(false);
_template.setCaching(false);
// set
_lastUpdated=TQDate(1900,1,1);
_wordList.clear();
_wordListUpdated = false;
update(parent()->isOpen(),false,true);
if( !isDir() ) setPixmap(COL_MARKER,ICON_NOFLAG);
}
void CatManListItem::setMarked(bool on)
{
if(on)
{
setPixmap(COL_MARKER,ICON_FLAG);
}
else
{
setPixmap(COL_MARKER,ICON_NOFLAG);
}
_marked=on;
}
bool CatManListItem::marked() const
{
if( isFile() ) return _marked;
else if( isDir() )
{
CatManListItem * myChild = (CatManListItem*)firstChild();
while( myChild )
{
if(myChild->isFile() && myChild->marked() ) return true;
else if(myChild->isDir() && myChild->marked() ) return true;
myChild = (CatManListItem*)myChild->nextSibling();
}
}
return false;
}
void CatManListItem::setOpen(bool open)
{
bool needWork = needsWork();
TQListViewItem::setOpen(open);
if(open && _type==Dir)
{
TQPixmap icon;
icon = needWork ? ICON_FOLDER_OPEN_WORK : ICON_FOLDER_OPEN_OK;
if(!_template.exists())
{
icon=paintExclamation(&icon);
}
setPixmap(COL_NAME,icon);
CatManListItem * myChild = (CatManListItem*)firstChild();
while( myChild )
{
myChild->checkUpdate();
myChild = (CatManListItem*)myChild->nextSibling();
}
}
else
{
TQPixmap icon;
if(needsWork())
icon = ICON_FOLDER_CLOSED_WORK;
else
icon = ICON_FOLDER_CLOSED_OK;
if(!_template.exists())
{
icon=paintExclamation(&icon);
}
setPixmap(COL_NAME,icon);
}
}
TQStringList CatManListItem::allChildrenList(bool onlyFiles) const
{
TQStringList tqchildrenList;
CatManListItem * myChild = (CatManListItem*)firstChild();
while( myChild )
{
TQString name=myChild->package();
if(myChild->isFile())
{
tqchildrenList.append(name);
}
else if(myChild->isDir())
{
if(!onlyFiles)
tqchildrenList.append(name);
tqchildrenList+=myChild->allChildrenList(onlyFiles);
}
myChild = (CatManListItem*)myChild->nextSibling();
}
return tqchildrenList;
}
TQStringList CatManListItem::allChildrenFileList(bool onlyFiles, bool emptyDirs, bool onlyModified) const
{
TQStringList tqchildrenList;
CatManListItem * myChild = (CatManListItem*)firstChild();
while( myChild )
{
if(myChild->isFile() && myChild->hasPo() &&
!(!myChild->isModified() && onlyModified))
{
tqchildrenList.append(myChild->poFile());
}
else if(myChild->isDir())
{
if(!onlyFiles && (emptyDirs || myChild->_primary.exists() ))
{
tqchildrenList.append(myChild->poFile());
}
tqchildrenList+=myChild->allChildrenFileList(onlyFiles,false,onlyModified);
}
myChild = (CatManListItem*)myChild->nextSibling();
}
return tqchildrenList;
}
TQStringList CatManListItem::contentsList(bool onlyFiles) const
{
TQStringList childList;
CatManListItem * myChild = (CatManListItem*)firstChild();
while( myChild )
{
TQString name=myChild->package();
if(onlyFiles)
{
if(myChild->isFile())
{
childList.append(name);
}
}
else
{
childList.append(name);
}
myChild = (CatManListItem*)myChild->nextSibling();
}
return childList;
}
void CatManListItem::forceUpdate()
{
update(true,true,false);
}
void CatManListItem::checkUpdate(bool noParents)
{
// if a file has disappeared or is new
if(_hasPo != hasPo() || _hasPot != hasPot())
{
update(true,false,noParents);
}
else if(!isFile())
{
update(true,false,noParents);
}
else if(_hasPo && _lastUpdated < _primary.lastModified())
{
update(true,false,noParents);
}
else if(_hasPot && _lastUpdated < _template.lastModified())
{
update(true,false,noParents);
}
}
TQString CatManListItem::key(int col, bool) const
{
// show directories first
TQString key=text(col);
if(col==COL_NAME)
{
if(_type==Dir)
{
key="a"+key;
}
else
{
key="b"+key;
}
}
// fuzzy, untranslated, total
else if(col==COL_FUZZY || col ==COL_TOTAL || col==COL_UNTRANS)
{
key=key.rightJustify(10,'0');
}
// marked po's
else if(col==COL_MARKER)
{
if(_marked)
{
key="1";
}
else
{
key="0";
}
}
return key;
}
void CatManListItem::update(bool showPoInfo,bool includeChildren
, bool noParents)
{
if( _view->isStopped() ) return; // if parent view is stopped, we should stop as well
bool updateWordList = _view->settings().indexWords;
// flag, if something has changed and parent has to be updated
bool updateParent=false;
// update flags for files...
const bool hadPo=_hasPo;
_hasPo = hasPo();
const bool hadPot = _hasPot;
_hasPot = hasPot();
// and check if something changed
if(hadPo != _hasPo || hadPot != _hasPot)
updateParent=true;
if(_package!="/") // don't update root item
{
if(_primary.exists())
{
if(_primary.isDir())
{
TQDir dir=_primary.dir();
setText(COL_NAME,dir.dirName());
// count the childen numbers
int fuzzy = 0;
int untrans = 0;
int total = 0;
CatManListItem* ch = static_cast<CatManListItem*>(firstChild ());
while (ch)
{
fuzzy += ch->fuzzy ();
untrans += ch->untranslated ();
total += ch->total ();
ch = static_cast<CatManListItem*>(ch->nextSibling());
}
setText(COL_FUZZY,TQString::number(fuzzy));
setText(COL_UNTRANS,TQString::number(untrans));
setText(COL_TOTAL,TQString::number(total));
//setSelectable(false);
_type=Dir;
bool needWork = needsWork();
TQPixmap icon;
if(!isOpen())
{
if( needWork )
icon = ICON_FOLDER_CLOSED_WORK;
else
icon = ICON_FOLDER_CLOSED_OK;
}
else
{
icon = needWork ? ICON_FOLDER_OPEN_WORK : ICON_FOLDER_OPEN_OK;
}
// check if the same directory exists also in the
// template directory
if(_template.isDir())
{
setPixmap( COL_NAME, icon );
}
else
{
TQPixmap folder = icon;
icon=paintExclamation(&folder);
setPixmap(COL_NAME,folder);
}
}
else // primary is file
{
_type=File;
TQString name=_primary.fileName();
setText(COL_NAME,name.left(name.length()-3));
if(showPoInfo)
{
_lastUpdated=TQDateTime::currentDateTime();
bool neededWork=needsWork();
bool needWork=false;
PoInfo poInfo;
TQPixmap icon = ICON_UPDATING;
setPixmap(COL_NAME,icon);
if ( PoInfo::info( _primary.absFilePath(), poInfo, _wordList, updateWordList, true, true ) == OK )
{
if( _view->isStopped() ) return;
if( updateWordList) _wordListUpdated = true;
_hasErrors=false;
const CVSHandler* cvsHandler = _view->cvsHandler();
const SVNHandler* svnHandler = _view->svnHandler();
const CVSHandler::FileStatus cvsFileStatus = cvsHandler->fstatus( poFile() );
const SVNHandler::FileStatus svnFileStatus = svnHandler->fstatus( poFile() );
_isModified = cvsHandler->isConsideredModified( cvsFileStatus )
|| svnHandler->isConsideredModified( svnFileStatus );
TQString versionControl;
if ( cvsFileStatus != CVSHandler::NO_REPOSITORY )
versionControl = cvsHandler->fileStatus( cvsFileStatus );
else if ( svnFileStatus != SVNHandler::NO_REPOSITORY )
versionControl = svnHandler->fileStatus( svnFileStatus );
else
versionControl = i18n("No version control");
setText(COL_FUZZY,TQString::number(poInfo.fuzzy));
setText(COL_UNTRANS,TQString::number(poInfo.untranslated));
setText(COL_TOTAL,TQString::number(poInfo.total));
setText( COL_CVS_OR_SVN, versionControl );
setText(COL_REVISION,poInfo.revision);
setText(COL_TRANSLATOR,poInfo.lastTranslator);
if(needsWork())
{
icon=ICON_NEEDWORK;
needWork = true;
}
else
{
icon = ICON_OK;
needWork=false;
}
}
else
{
kdDebug(KBABEL_CATMAN) << "This file is broken" << endl;
if( _view->isStopped() ) return;
_hasErrors=true;
icon = ICON_BROKEN;
needWork=true;
}
if(!_template.exists())
{
icon=paintExclamation(&icon);
}
setPixmap(COL_NAME,icon);
updateParent=true;
}
}
}
// only the template exists
else if(_template.exists())
{
if(_template.isDir())
{
TQDir dir=_template.dir();
setText(COL_NAME,dir.dirName());
//setSelectable(false);
_type=Dir;
// count the childen numbers
int total = 0;
CatManListItem* ch = static_cast<CatManListItem*>(firstChild ());
while (ch)
{
total += ch->total ();
ch = static_cast<CatManListItem*>(ch->nextSibling());
}
setText(COL_TOTAL,TQString::number(total));
TQPixmap icon;
if(!isOpen())
{
icon = ICON_FOLDER_CLOSED_WORK;
}
else
{
icon = needsWork() ? ICON_FOLDER_OPEN_WORK : ICON_FOLDER_OPEN_OK;
}
setPixmap(COL_NAME, icon );
}
// item is file
else
{
_type=File;
TQString name=_primary.fileName();
setText(COL_NAME,name.left(name.length()-3));
if(showPoInfo)
{
_lastUpdated=TQDateTime::currentDateTime();
// clean previous state information
setText(COL_FUZZY,TQString());
setText(COL_UNTRANS,TQString());
setText(COL_TOTAL,TQString());
setText(COL_CVS_OR_SVN, TQString());
setText(COL_REVISION, TQString());
setText(COL_TRANSLATOR, TQString());
setPixmap(COL_NAME,ICON_UPDATING);
PoInfo poInfo;
if ( PoInfo::info( _template.absFilePath(), poInfo, _wordList, false, true, true ) == OK )
{
if( _view->isStopped() ) return;
setText(COL_TOTAL,TQString::number(poInfo.total));
}
if( _view->isStopped() ) return;
}
setPixmap(COL_NAME,ICON_MISSING);
updateParent = true;
}
}
else
{
kdWarning(KBABEL_CATMAN) << "whether po nor pot exists: " << _package << endl;
}
}
_view->fileInfoRead( package() );
if( _view->isStopped() ) return;
if(updateParent && !noParents)
{
updateParents();
}
if( _view->isStopped() ) return;
if(includeChildren)
{
CatManListItem *myChild = (CatManListItem*)firstChild();
while( myChild )
{
myChild->update(showPoInfo,includeChildren);
myChild = (CatManListItem*)myChild->nextSibling();
}
}
// HACK to get the signal emitted
if (isSelected( )) {
listView( )->setSelected(this, false);
listView( )->setSelected(this, true);
}
}
// we know that this item was saved and PoInfo contains new information
// about this item, the item is file
// however, is can be saved template or translation!!! - only translation is handled???
void CatManListItem::updateAfterSave( PoInfo &poInfo )
{
// flag, if something has changed and parent has to be updated
bool updateParent=false;
// update flags for files...
const bool hadPo=_hasPo;
_hasPo = hasPo();
const bool hadPot = _hasPot;
_hasPot = hasPot();
// and check if something changed
if(hadPo != _hasPo || hadPot != _hasPot)
updateParent=true;
if(_primary.exists())
{
// primary is existent file
_type=File;
TQString name=_primary.fileName();
setText(COL_NAME,name.left(name.length()-3));
_lastUpdated=TQDateTime::currentDateTime();
bool neededWork=needsWork();
bool needWork=false;
TQPixmap icon;
_hasErrors=false;
const CVSHandler::FileStatus cvsFileStatus = _view->cvsHandler()->fstatus(poFile());
const SVNHandler::FileStatus svnFileStatus = _view->svnHandler()->fstatus(poFile());
TQString versionControl;
if ( cvsFileStatus != CVSHandler::NO_REPOSITORY )
versionControl = _view->cvsHandler()->fileStatus( cvsFileStatus );
else if ( svnFileStatus != SVNHandler::NO_REPOSITORY )
versionControl = _view->svnHandler()->fileStatus( svnFileStatus );
else
versionControl = i18n("No version control");
setText(COL_FUZZY,TQString::number(poInfo.fuzzy));
setText(COL_UNTRANS,TQString::number(poInfo.untranslated));
setText(COL_TOTAL,TQString::number(poInfo.total));
setText( COL_CVS_OR_SVN, versionControl );
setText(COL_REVISION,poInfo.revision);
setText(COL_TRANSLATOR,poInfo.lastTranslator);
if(needsWork())
{
icon=ICON_NEEDWORK;
needWork = true;
}
else
{
icon = ICON_OK;
needWork=false;
}
if(!_template.exists())
{
icon=paintExclamation(&icon);
}
setPixmap(COL_NAME,icon);
// if the status changed, update the parent item
if(needWork != neededWork)
{
updateParent=true;
}
}
if(updateParent)
{
updateParents();
}
}
void CatManListItem::updateParents()
{
CatManListItem *item = (CatManListItem*)parent();
while( item && !_view->isStopped())
{
item->update(false,false);
item = (CatManListItem*)item->parent();
}
}
bool CatManListItem::hasPo() const
{
return _primary.exists();
}
bool CatManListItem::hasPot() const
{
return _template.exists();
}
bool CatManListItem::isModified() const
{
return _isModified;
}
int CatManListItem::fuzzy() const
{
bool success;
int number=text(COL_FUZZY).toInt(&success);
if(!success)
number=0;
return number;
}
int CatManListItem::untranslated() const
{
bool success;
int number;
if( !hasPo() )
{
number=total();
}
else
{
number=text(COL_UNTRANS).toInt(&success);
if(!success)
number=0;
}
return number;
}
int CatManListItem::total() const
{
bool success;
int number=text(COL_TOTAL).toInt(&success);
if(!success)
number=0;
return number;
}
bool CatManListItem::needsWork() const
{
bool flag=false;
if(isFile())
{
if(!hasPo() || fuzzy() > 0 || untranslated() > 0 || _hasErrors)
flag=true;
}
else
{
CatManListItem *myChild = (CatManListItem*)firstChild();
while( myChild )
{
if( myChild->needsWork() )
{
flag=true;
myChild=0;
}
else
{
myChild = (CatManListItem*)myChild->nextSibling();
}
}
}
return flag;
}
bool CatManListItem::isDir() const
{
return type()==Dir;
}
bool CatManListItem::isFile() const
{
return type()==File;
}
TQString CatManListItem::poFile() const
{
return _primary.absFilePath();
}
TQString CatManListItem::potFile() const
{
return _template.absFilePath();
}
TQString CatManListItem::package(bool rootSlash) const
{
if(rootSlash)
return _package;
else
{
return _package.right(_package.length()-1);
}
}
TQString CatManListItem::packageDir( ) const
{
return ( _type == Dir ? _package : TQString() );
}
TQString CatManListItem::name() const
{
int index = _package.findRev("/");
return _package.right(_package.length()-index-1);
}
TQPixmap CatManListItem::paintExclamation(TQPixmap* pixmap)
{
if(!pixmap || pixmap->isNull())
return TQPixmap(0,0);
if(_package=="/" && _template.filePath().isEmpty())
return *pixmap;
if(isDir() && _package == _template.filePath())
return *pixmap;
if(isFile() && _package+".pot" == _template.filePath())
return *pixmap;
int width=pixmap->width();
int height=pixmap->height();
int diameter=TQMIN(width,height);
TQBitmap mask=pixmap->createHeuristicMask();
TQPainter mp(&mask);
mp.setPen(TQPen(TQt::color1,1));
mp.drawEllipse(width-diameter,height-diameter,diameter,diameter);
TQPixmap result(width,height);
TQPainter p(&result);
p.drawPixmap(0,0,*pixmap);
p.setPen( TQPen(red,1) );
p.drawEllipse(width-diameter,height-diameter,diameter,diameter);
result.setMask(mask);
return result;
}
TQListViewItem *CatManListItem::previousSibling()
{
TQListViewItem * i = parent();
if( !i ) return i;
i = i->firstChild();
if( !i ) return i;
if( i == this ) return 0;
while( i->nextSibling()!=this ) i = i->nextSibling();
return i;
}
TQListViewItem *CatManListItem::lastChild()
{
TQListViewItem * i = firstChild();
if( !i ) return i;
while( i->nextSibling() ) i = i->nextSibling();
return i;
}
void CatManListItem::checkErrors(KDataTool* tool, TQObject* progressSignalHandler, bool ignoreFuzzy, bool markAsFuzzy)
{
bool hasError=false;
_errors.clear();
Catalog* cat = new Catalog();
TQObject::connect( cat, TQT_SIGNAL( signalProgress(int) ), progressSignalHandler, TQT_SIGNAL( setValidationProgressBar(int)));
TQObject::connect( cat, TQT_SIGNAL( signalResetProgressBar(TQString, int) ), progressSignalHandler, TQT_SLOT( setupFileProgressBar(TQString, int)));
if( cat->openURL(KURL( poFile() )) == OK )
{
kdDebug(KBABEL_CATMAN) << "File opened succesfully" << endl;
if( !cat->checkUsingTool(tool,true) )
{
hasError = true;
} else forceUpdate(); // no error, find out the new state
} else {
kdDebug(KBABEL_CATMAN) << "File not opened !!!!!" << endl;
hasError=true;
}
if( hasError )
{
TQString errortext;
_hasErrors = true;
DocPosition dummy;
IgnoreItem i;
i.fileURL = poFile();
if( cat->hasError(0,dummy) && (!ignoreFuzzy || !cat->isFuzzy(0)))
{
i.msgid = cat->msgid(0);
i.msgstr = cat->msgstr(0);
i.index = 0;
_errors.append( i );
if( markAsFuzzy ) cat->setFuzzy(0, true);
}
int index=0;
do
{
index=cat->nextError(index,dummy);
if( index != -1 && (!ignoreFuzzy || !cat->isFuzzy(index) ) )
{
i.msgid = cat->msgid(index);
i.msgstr = cat->msgstr(index);
i.index = index;
_errors.append( i );
if( markAsFuzzy ) cat->setFuzzy(index, true);
}
} while(index>=0);
// change icon only if there were non-ignored errors
if( !_errors.isEmpty() )
{
setPixmap(COL_NAME, ICON_ERROR);
}
// if we changed fuzzy flags, save the result
if( cat->isModified() ) cat->saveFile();
}
delete cat;
}