diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | bd9e6617827818fd043452c08c606f07b78014a0 (patch) | |
tree | 425bb4c3168f9c02f10150f235d2cb998dcc6108 /kbabel/catalogmanager/catalogmanagerview.cpp | |
download | tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.tar.gz tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdesdk@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kbabel/catalogmanager/catalogmanagerview.cpp')
-rw-r--r-- | kbabel/catalogmanager/catalogmanagerview.cpp | 3132 |
1 files changed, 3132 insertions, 0 deletions
diff --git a/kbabel/catalogmanager/catalogmanagerview.cpp b/kbabel/catalogmanager/catalogmanagerview.cpp new file mode 100644 index 00000000..6bb4c88f --- /dev/null +++ b/kbabel/catalogmanager/catalogmanagerview.cpp @@ -0,0 +1,3132 @@ +/* **************************************************************************** + This file is part of KBabel + + Copyright (C) 1999-2000 by Matthias Kiefer + <matthias.kiefer@gmx.de> + 2001-2004 by Stanislav Visnovsky + <visnovsky@kde.org> + Copyright (C) 2005, 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 Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), 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 + Qt. 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 "catalogmanager.h" +#include "catmanlistitem.h" +#include "catalog.h" +#include "kbabeldictbox.h" + +#include "resources.h" +#include "multiroughtransdlg.h" +#include "msgfmt.h" +#include "kbmailer.h" +#include "validateprogress.h" +#include "cvshandler.h" +#include "svnhandler.h" +#include "markpatterndialog.h" +#include "validationoptions.h" + +#include <qcheckbox.h> +#include <qpopupmenu.h> +#include <qlabel.h> +#include <qpainter.h> + +#include <kcmenumngr.h> +#include <kcursor.h> +#include <klocale.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kconfig.h> +#include <kdatatool.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include <kaction.h> +#include <kfiledialog.h> +#include <kio/netaccess.h> +#include <kprogress.h> +#include <kwin.h> +#include <kdeversion.h> +#include <ktempfile.h> + +#include <qfileinfo.h> +#include <qdir.h> +#include <qtimer.h> +#include <qbitmap.h> +#include <qwhatsthis.h> +#include <qheader.h> +#include <qdragobject.h> +#include <qlayout.h> +#include <qtextedit.h> + +using namespace KBabel; + +const char* columnNames[] = { + I18N_NOOP("Name"), + I18N_NOOP("M"), + I18N_NOOP("Fuzzy"), + I18N_NOOP("Untranslated"), + I18N_NOOP("Total"), + I18N_NOOP("CVS/SVN Status"), + I18N_NOOP("Last Revision"), + I18N_NOOP("Last Translator") +}; + +#define COLTEXT(a) (i18n(columnNames[a])) + +CatalogManagerView::CatalogManagerView(KBabel::Project::Ptr project, QWidget* parent,const char* name) + : QListView(parent,name) + , _dirWatch(0) + , _readInfoCount(0) + , _active(false) + , _stop(false) + , _stopSearch(false) + , _updateNesting(0) + , _logView(0) + , _logWindow(0) + , m_validPOCVSRepository( false ) + , m_validPOTCVSRepository( false ) + , m_validPOSVNRepository( false ) + , m_validPOTSVNRepository( false ) + , markPatternDialog(0) + , _validateDialog(0) + , _validateOptions(0) + , _validateOptionsDlg(0) + , _markAsFuzzy(false) + , _ignoreFuzzy(false) + , _project(project) +{ + _dirList.resize(200); + _fileList.resize(500); + _readInfoFileList.clear(); + + _pendingProcesses.setAutoDelete(true); + + setSelectionMode(Single); + + _dictBox = new KBabelDictBox(this, "dictbox"); + _dictBox->hide(); + + _updateTimer = new QTimer(this); + connect(_updateTimer,SIGNAL(timeout()),this,SLOT(checkUpdate())); + + addColumn(COLTEXT(COL_NAME)); + addColumn(COLTEXT(COL_MARKER),25); + setColumnAlignment(1,AlignCenter); + addColumn(COLTEXT(COL_FUZZY)); + setColumnAlignment(1,AlignCenter); + addColumn(COLTEXT(COL_UNTRANS)); + setColumnAlignment(2,AlignCenter); + addColumn(COLTEXT(COL_TOTAL)); + setColumnAlignment(3,AlignCenter); + addColumn(QString::null); // CVS/SVN column, header is set later + addColumn(COLTEXT(COL_REVISION)); + addColumn(COLTEXT(COL_TRANSLATOR)); + + + header()->setMovingEnabled(false); + setAllColumnsShowFocus(true); + setSorting(0); + + if(KContextMenuManager::showOnButtonPress()) + { + connect(this,SIGNAL(rightButtonPressed(QListViewItem*,const QPoint &, int)) + ,this, SLOT(showContentsMenu(QListViewItem*,const QPoint &, int))); + } + else + { + connect(this,SIGNAL(rightButtonClicked(QListViewItem*,const QPoint &, int)) + ,this, SLOT(showContentsMenu(QListViewItem*,const QPoint &, int))); + } + connect(this, SIGNAL(returnPressed(QListViewItem*)) + ,this, SLOT(activateItem(QListViewItem*))); + connect(this, SIGNAL(doubleClicked(QListViewItem*)) + ,this, SLOT(activateItem(QListViewItem*))); + connect(this,SIGNAL(selectionChanged()),this,SLOT(checkSelected())); + connect( this, SIGNAL( clicked(QListViewItem *, const QPoint &, int)), + this, SLOT( columnClicked(QListViewItem *, const QPoint &, int))); + + _dirCommandsMenu = 0; + _fileCommandsMenu = 0; + _dirContentsMenu = 0; + _fileContentsMenu = 0; + + _logWindow = new KDialogBase(0,"log window",false,i18n("Log Window") + ,KDialogBase::Close | KDialogBase::User1,KDialogBase::Close); + _logWindow->setButtonText(KDialogBase::User1,i18n("C&lear")); + _logWindow->setInitialSize(QSize(300,200)); + + QWhatsThis::add(_logWindow,i18n("<qt><p><b>Log window</b></p>\n" + "<p>In this window the output of " + "the executed commands are shown.</p></qt>")); + + _logView = new QTextEdit(_logWindow); + _logView->setReadOnly(true); + + _logWindow->setMainWidget(_logView); + + connect(_logWindow,SIGNAL(user1Clicked()),_logView,SLOT(clear())); + + QWhatsThis::add(this,i18n("<qt><p><b>Catalog Manager</b></p>\n" +"<p>The Catalog Manager merges two folders into one tree and displays all\n" +"PO and POT files in these folders. This way you can easily see if a\n" +"template has been added or removed. Also some information about the files\n" +"is displayed.</p>" +"<p>For more information see section <b>The Catalog Manager</b>" +" in the online help.</p></qt>")); + + setAcceptDrops(true); // just to get the drag displayed immediately + + mailer = new KBabelMailer( this, _project ); + + // CVS + cvshandler = new CVSHandler( ); + connect( cvshandler, SIGNAL( signalIsPORepository( bool ) ), + this, SLOT( slotValidPOCVSRepository( bool ) ) ); + connect( cvshandler, SIGNAL( signalIsPOTRepository( bool ) ), + this, SLOT( slotValidPOTCVSRepository( bool ) ) ); + connect( cvshandler, SIGNAL( signalFilesCommitted( const QStringList& ) ), + this, SLOT( updateFiles( const QStringList& ) ) ); + + // SVN + svnhandler = new SVNHandler( ); + connect( svnhandler, SIGNAL( signalIsPORepository( bool ) ), + this, SLOT( slotValidPOSVNRepository( bool ) ) ); + connect( svnhandler, SIGNAL( signalIsPOTRepository( bool ) ), + this, SLOT( slotValidPOTSVNRepository( bool ) ) ); + connect( svnhandler, SIGNAL( signalFilesCommitted( const QStringList& ) ), + this, SLOT( updateFiles( const QStringList& ) ) ); + + KConfig *config = KGlobal::config(); + restoreView(config); + + _dictBox->readSettings(_project->config()); +} + +CatalogManagerView::~CatalogManagerView() +{ + if(_active) + stop(); + + if(_dirWatch) + delete _dirWatch; + + if(_settings.killCmdOnExit) + { + KProcess* proc; + for ( proc=_pendingProcesses.first(); proc != 0; proc=_pendingProcesses.next() ) + { + proc->kill(SIGKILL); + } + } + + delete _logWindow; + delete mailer; + delete cvshandler; + delete svnhandler; + if (markPatternDialog) delete markPatternDialog; +} + + +void CatalogManagerView::saveView( KConfig *config) const +{ + saveMarker(config); + + KConfigGroupSaver( config, "CatalogManager" ); + + config->writeEntry( "ValidateMarkAsFuzzy", _markAsFuzzy ); + config->writeEntry( "ValidateIgnoreFuzzy", _ignoreFuzzy ); +} + + +void CatalogManagerView::restoreView( KConfig *config) +{ + readMarker(config); + + _markAsFuzzy = config->readBoolEntry( "ValidateMarkAsFuzzy", false ); + _ignoreFuzzy = config->readBoolEntry( "ValidateIgnoreFuzzy", false ); +} + +void CatalogManagerView::setRMBMenuFile( QPopupMenu *m ) +{ + _fileContentsMenu = m; +} + +void CatalogManagerView::setRMBMenuDir( QPopupMenu *m ) +{ + _dirContentsMenu = m; +} + +void CatalogManagerView::setDirCommandsMenu( QPopupMenu *m ) +{ + _dirCommandsMenu = m; + connect(_dirCommandsMenu,SIGNAL(activated(int)),this,SLOT(slotDirCommand(int))); +} + +void CatalogManagerView::setFileCommandsMenu( QPopupMenu *m ) +{ + _fileCommandsMenu = m; + connect(_fileCommandsMenu,SIGNAL(activated(int)),this,SLOT(slotFileCommand(int))); +} + +void CatalogManagerView::checkUpdate() +{ + _updateNesting++; + pause(true); + + QDictIterator<CatManListItem> it( _fileList ); // iterator for dict + + while ( it.current() && !_stop) + { + CatManListItem* item=it.current(); + + item->checkUpdate(); + ++it; + } + + pause(false); + --_updateNesting; + if( _updateNesting == 0 ) + { + emit updateFinished(); + } +} + + + +void CatalogManagerView::pause(bool flag) +{ + if(flag) + { + _updateTimer->stop(); + } + else + { + _updateTimer->start(10000); + } +} + + +void CatalogManagerView::stop(bool s) +{ + kdDebug(KBABEL_CATMAN) << "Stopping " << s << endl; + pause(s); + _stop=s; + PoInfo::stopStaticRead = true; +} + +void CatalogManagerView::stopSearch() +{ + _stopSearch = true; +} + +void CatalogManagerView::clear() +{ + pause(true); + + // first clear up + if(_dirWatch) + delete _dirWatch; + + _dirWatch= new KDirWatch(); + connect(_dirWatch,SIGNAL(deleted(const QString&)),this + ,SLOT(directoryDeleted(const QString&))); + connect(_dirWatch,SIGNAL(dirty(const QString&)),this + ,SLOT(directoryChanged(const QString&))); + connect(_dirWatch,SIGNAL(created(const QString&)),this + ,SLOT(directoryChanged(const QString&))); + + _dirList.clear(); + _fileList.clear(); + + QListView::clear(); +} + +void CatalogManagerView::toggleAllMarks() +{ + _markerList.clear(); + + QListViewItemIterator it( this ); + CatManListItem* item; + + for ( ; it.current(); ++it ) + { + item = (CatManListItem*) it.current(); + if(item->isFile()) + { + bool wasMarked=item->marked(); + item->setMarked(!wasMarked); + if(!wasMarked) + { + _markerList.append(item->package()); + } + else + { + _markerList.remove(item->package()); + } + } + } + + checkSelected(); +} + +void CatalogManagerView::clearAllMarks() +{ + _markerList.clear(); + QDictIterator<CatManListItem> it( _fileList ); // iterator for dict + + while ( it.current() ) + { + CatManListItem* item=it.current(); + + if(item->marked()) + _markerList.remove(item->package()); + + item->setMarked(false); + ++it; + } + + checkSelected(); +} + +void CatalogManagerView::markModifiedFiles() +{ + QDictIterator<CatManListItem> it( _fileList ); + while ( it.current() ) + { + CatManListItem* item=it.current(); + /*if(item->marked()) + _markerList.remove(item->package()); + */ + if(item->isModified() && ! item->marked() ) { + item->setMarked(true); + _markerList.append(item->package( )); + } + ++it; + } + + checkSelected(); +} + +void CatalogManagerView::loadMarks() +{ + const KURL url = KFileDialog::getOpenURL( QString(),"*.marklist", this ); + if( url.isEmpty() ) return; + + QString filename; +#if KDE_IS_VERSION( 3, 2, 90 ) + if (!KIO::NetAccess::download( url, filename, this ) ) +#else + if( !KIO::NetAccess::download( url, filename ) ) +#endif + { + KMessageBox::error(this,i18n( + "Error while trying to open file:\n %1").arg(url.prettyURL())); + return; + } + + // now load from file + QStringList newMarkerList; // better create new list in case of problems + QFile f( filename ); + if( f.open( IO_ReadOnly) ) + { + QTextStream s(&f); + + QString input; + + s >> input ; + if( input == "[Markers]" ) + { + while( !s.atEnd() ) + { + s >> input; + newMarkerList.append(input); + } + } + else + { + KMessageBox::error(this + ,i18n("Error while trying to read file:\n %1\n" + "Maybe it is not a valid file with list of markings.").arg(url.prettyURL())); + f.close(); + return; + } + f.close(); + } + else + { + KMessageBox::error(this,i18n( + "Error while trying to open file:\n %1").arg(url.prettyURL())); + } + + KIO::NetAccess::removeTempFile( filename ); + + // test validity of list items + QStringList testedList; + QStringList::const_iterator it; + for( it=newMarkerList.constBegin() ; it!=newMarkerList.constEnd() ; ++it ) + if( _fileList[(*it)] != 0 ) testedList.append( (*it) ); + + // apply new list + for( it=_markerList.constBegin() ; it!=_markerList.constEnd() ; ++it ) + { + CatManListItem* item = _fileList[(*it)]; + if( item ) item->setMarked(false); + } + + _markerList = testedList; + for( it=_markerList.constBegin() ; it!=_markerList.constEnd() ; ++it ) + { + CatManListItem* item = _fileList[(*it)]; + if( item ) item->setMarked(true); + } + + checkSelected(); +} + +void CatalogManagerView::saveMarks() +{ + const KURL url2 = KFileDialog::getSaveURL( QString(), "*.marklist", this ); + if( url2.isEmpty() ) return; + + // ### FIXME: why is the file dialog not doing this? + if ( KIO::NetAccess::exists( url2, false, this ) ) + { + if(KMessageBox::warningContinueCancel(this,QString("<qt>%1</qt>").arg(i18n("The file %1 already exists. " + "Do you want to overwrite it?").arg(url2.prettyURL())),i18n("Warning"),i18n("&Overwrite"))==KMessageBox::Cancel) + { + return; + } + } + +#if KDE_IS_VERSION( 3, 4, 92 ) + // Support for partially remote KIO slave like media: + const KURL url ( KIO::NetAccess::mostLocalURL( url2, this ) ); +#else + const KURL url ( url2 ); +#endif + kdDebug() << "Saving marks: " << url2.prettyURL() << " most-local: " << url.prettyURL() << endl; + + QFile* file = 0; + KTempFile* tempFile = 0; + QTextStream* stream = 0; + bool error = false; + + const bool localFile = url.isLocalFile(); + if ( localFile ) + { + // We have a local file + file = new QFile( url.path() ); + if ( file->open (IO_WriteOnly) ) + { + stream = new QTextStream( file ); + } + else + { + error = true; + } + } + else + { + tempFile = new KTempFile(); + tempFile->setAutoDelete(true); + stream = tempFile->textStream(); + error = !stream; + } + if ( !error ) + { + // ### TODO: try to get a better file format for KDE4 (XML?), one working with real relative paths (no / at start) and working with UTF-8 + *stream << "[Markers]" << endl; + for( QStringList::const_iterator it = _markerList.constBegin(); it!=_markerList.constEnd() ; ++it ) + *stream << (*it) << endl; + } + if ( error ) + { + // ### KDE4 FIXME: strip the final \n of the message + KMessageBox::error( this, + i18n( "An error occurred while trying to write to file:\n%1\n" ).arg( url.prettyURL()) ); + } + else if ( !localFile ) + { + tempFile->close(); + if( !KIO::NetAccess::upload( tempFile->name(), url, this ) ) + { + // ### KDE4 FIXME: strip the final \n of the message + KMessageBox::error(this, + i18n("An error occurred while trying to upload the file:\n%1\n").arg(url.prettyURL())); + } + } + + // We have finished so clean up + if ( localFile ) + { + delete stream; + file->close(); + delete file; + } + else + { + delete tempFile; + } + + checkSelected(); +} + +void CatalogManagerView::slotMarkPattern( ) +{ + setPatternMarks(true); +} + +void CatalogManagerView::slotUnmarkPattern( ) +{ + setPatternMarks(false); +} + +void CatalogManagerView::setPatternMarks(bool mark) +{ + CatManListItem * item = (CatManListItem*)currentItem( ); + if (!item) + item = (CatManListItem*)_dirList["/"]; + if (!item->isDir( )) + return; + + if (!markPatternDialog) + markPatternDialog = new MarkPatternDialog(this); + + markPatternDialog->setMode(mark); + + if (markPatternDialog->exec( ) != KDialog::Accepted) + return; + + QRegExp rx(markPatternDialog->pattern( )); + rx.setWildcard(!markPatternDialog->useRegExp( )); + rx.setCaseSensitive(markPatternDialog->isCaseSensitive( )); + + QStringList fileList = item->allChildrenList(true); + for (QStringList::const_iterator it = fileList.constBegin( ); it != fileList.constEnd( ); ++it) { + CatManListItem * i = _fileList[*it]; + + QString matchName; + if (i->hasPo( )) + matchName = i->poFile( ); + else if (i->hasPot( ) && markPatternDialog->includeTemplates( )) + matchName = i->potFile( ); + matchName = QFileInfo(matchName).baseName( ); + + if (mark) { + if (!matchName.isEmpty( ) && rx.exactMatch(matchName) && !i->marked( )) { + i->setMarked(true); + _markerList.append(i->package( )); + } + } else { + if (!matchName.isEmpty( ) && rx.exactMatch(matchName) && i->marked( )) { + i->setMarked(false); + _markerList.remove(i->package( )); + } + } + } +} + +void CatalogManagerView::statistics() +{ + CatManListItem* i=(CatManListItem*) currentItem(); + + if(!i) + i=(CatManListItem*)_dirList["/"]; + + if(isActive() && i->isDir()) + { + if(KMessageBox::warningContinueCancel(this + ,i18n("The Catalog Manager is still updating information about the files.\n" +"If you continue, it will try to update all necessary files, however this can take " +"a long time and may lead to wrong results. Please wait until all files are updated."),i18n("Warning") + ,KStdGuiItem::cont()) == KMessageBox::Cancel) + { + return; + } + } + + QStringList doList; + + if( i->isFile() ) doList.append(i->package()); + else doList = i->allChildrenList(true); + + showStatistics( i, doList ); +} + +void CatalogManagerView::markedStatistics() +{ + CatManListItem* i=(CatManListItem*) currentItem(); + + if(!i) + i=(CatManListItem*)_dirList["/"]; + + if(isActive() && i->isDir()) + { + if(KMessageBox::warningContinueCancel(this + ,i18n("The Catalog Manager is still updating information about the files.\n" +"If you continue, it will try to update all necessary files, however this can take " +"a long time and may lead to wrong results. Please wait until all files are updated."),i18n("Warning") + ,KStdGuiItem::cont()) == KMessageBox::Cancel) + { + return; + } + } + + QStringList doList; + + if( i->isFile() ) doList.append(i->package()); + else doList = i->allChildrenList(true); + + QStringList markedDoList; + QStringList::const_iterator it; + for( it = doList.constBegin(); it != doList.constEnd(); ++it ) + { + CatManListItem* item = _fileList[(*it)]; + if( item->marked() ) markedDoList.append(item->package()); + } + + showStatistics( i, markedDoList ); +} + +void CatalogManagerView::showStatistics( CatManListItem *i, QStringList &childrenList ) +{ + KLocale *locale = KGlobal::locale(); + + QString msg; + int totalPackages=0; + int totalPo=0; + int totalNoPot=0; + int needworkPo=0; + int totalMsgid=0; + int totalFuzzy=0; + int totalUntranslated=0; + + QStringList::const_iterator it; + for( it = childrenList.constBegin(); it != childrenList.constEnd(); ++it ) + { + CatManListItem* item = _fileList[(*it)]; + + /* + KASSERT1(item,KDEBUG_FATAL,KBABEL_CATMAN,"CatalogManagerView::statistics: item not in list %s" + ,(*it).ascii()); + */ + // be sure, that the information is updated + _updateNesting++; + item->checkUpdate(); + _updateNesting--; + if( _stop ) return; + + totalPackages++; + + int fuzzy=item->fuzzy(); + int total=item->total(); + int untrans=item->untranslated(); + + if(item->hasPo()) + totalPo++; + + if(!item->hasPot()) + totalNoPot++; + + + if(fuzzy || untrans) + needworkPo++; + + totalMsgid+=total; + totalFuzzy+=fuzzy; + totalUntranslated+=untrans; + } + + double percent; + + const QString name=i->package(false); + if(name.isEmpty()) + msg = i18n("Statistics for all:\n"); + else + msg = i18n("Statistics for %1:\n").arg(name); + + msg+=i18n("Number of packages: %1\n").arg(locale->formatNumber(totalPackages, 0)); + + percent=100.0-((double)needworkPo*100.0)/totalPackages; + msg+=i18n("Complete translated: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalPackages-needworkPo, 0)); + + percent=100.0-((double)totalPo*100.0)/totalPackages; + msg+=i18n("Only template available: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalPackages-totalPo,0)); + percent=((double)totalNoPot*100.0)/totalPackages; + msg+=i18n("Only PO file available: %1 % (%2)\n").arg(locale->formatNumber(percent,02)).arg(locale->formatNumber(totalNoPot, 0)); + + msg+=i18n("Number of messages: %1\n").arg(locale->formatNumber(totalMsgid, 0)); + + long int totalTranslated = totalMsgid - totalFuzzy - totalUntranslated; + percent=((double)totalTranslated*100.0)/totalMsgid; + msg+=i18n("Translated: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalTranslated, 0)); + + percent=((double)totalFuzzy*100.0)/totalMsgid; + msg+=i18n("Fuzzy: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalFuzzy, 0)); + + percent=((double)totalUntranslated*100.0)/totalMsgid; + msg+=i18n("Untranslated: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalUntranslated, 0)); + + KMessageBox::information(this,msg,i18n("Statistics")); +} + +void CatalogManagerView::checkSyntax() +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + if(!item) + item=(CatManListItem*) _dirList["/"]; + + if(item->isFile()) + { + if(!item->hasPo()) + return; + + Msgfmt::Status status; + QString output; + Msgfmt msgfmt; + + status=msgfmt.checkSyntax(item->poFile(),output); + + switch(status) + { + case Msgfmt::Ok: + { + KMessageBox::information(this,i18n("The file is syntactically correct.\nOutput of \"msgfmt --statistics\":")+"\n"+output); + break; + } + case Msgfmt::SyntaxError: + { + KMessageBox::information(this,i18n("The file has syntax errors.\nOutput of \"msgfmt --statistics\":")+"\n"+output); + break; + } + case Msgfmt::HeaderError: + { + KMessageBox::information(this,i18n("The file has header syntax error.\nOutput of \"msgfmt --statistics\":")+"\n"+output); + break; + } + case Msgfmt::Error: + { + KMessageBox::error(this,i18n("An error occurred while processing \"msgfmt --statistics\"")); + break; + } + case Msgfmt::NoExecutable: + { + KMessageBox::sorry(this,i18n("Cannot execute msgfmt. Please make sure that you have msgfmt in your PATH.")); + break; + } + case Msgfmt::Unsupported: + { + KMessageBox::sorry(this,i18n("You can use gettext tools only for checking PO files.")); + break; + } + } + + } + else + { + Msgfmt::Status status; + QString output; + Msgfmt msgfmt; + + status=msgfmt.checkSyntaxInDir(item->poFile(), "*.po", output); + + QString name=item->package(false); + + switch(status) + { + case Msgfmt::Ok: + { + QString msg; + if(!name.isEmpty()) + { + msg=i18n("All files in folder %1 are syntactically correct.\n" +"Output of \"msgfmt --statistics\":\n").arg(name)+output; + } + else + { + msg=i18n("All files in the base folder are syntactically correct.\n" +"Output of \"msgfmt --statistics\":\n")+output; + } + KMessageBox::information(this,msg); + break; + } + case Msgfmt::SyntaxError: + { + QString msg; + if(!name.isEmpty()) + { + msg=i18n("At least one file in folder %1 has syntax errors.\n" +"Output of \"msgfmt --statistics\":\n").arg(name)+output; + } + else + { + msg=i18n("At least one file in the base folder has syntax errors.\n" +"Output of \"msgfmt --statistics\":\n")+output; + } + KMessageBox::information(this,msg); + break; + } + case Msgfmt::HeaderError: + { + QString msg; + if(!name.isEmpty()) + { + msg=i18n("At least one file in folder %1 has header syntax errors.\n" +"Output of \"msgfmt --statistics\":\n").arg(name)+output; + } + else + { + msg=i18n("At least one file in the base folder has header syntax errors.\n" +"Output of \"msgfmt --statistics\":\n")+output; + } + KMessageBox::information(this,msg); + break; + } + case Msgfmt::Error: + { + QString msg; + if(!name.isEmpty()) + { + msg=i18n("An error occurred while processing \"msgfmt --statistics *.po\" " +"in folder %1").arg(name); + } + else + { + msg=i18n("An error occurred while processing \"msgfmt --statistics *.po\" " +"in the base folder"); + } + KMessageBox::error(this,msg); + break; + } + case Msgfmt::NoExecutable: + { + KMessageBox::sorry(this,i18n("Cannot execute msgfmt. Please make sure that you have msgfmt in your PATH.")); + break; + } + case Msgfmt::Unsupported: + { + KMessageBox::sorry(this,i18n("You can use gettext tools only for checking PO files.")); + break; + } + } + } +} + +void CatalogManagerView::roughTranslation() +{ + QPtrList<CatManListItem> result; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + if( current->isDir() ) + { + QStringList s = current->allChildrenList(true); + QStringList::const_iterator it; + for( it = s.constBegin() ; it != s.constEnd(); ++it ) + { + CatManListItem *item = _fileList[(*it)]; + if( item ) result.append( item ); + } + } + else + { + result.append( current ); + } + + MultiRoughTransDlg* dialog=new MultiRoughTransDlg( _dictBox, result, this ); + dialog->exec(); + delete dialog; +} + +void CatalogManagerView::markedRoughTranslation() +{ + if( _markerList.count() == 0 ) return; + + QPtrList<CatManListItem> result; + + QStringList::const_iterator it; + for( it = _markerList.constBegin() ; it != _markerList.constEnd(); ++it ) + { + CatManListItem *item = _fileList[(*it)]; + result.append( item ); + } + + MultiRoughTransDlg* dialog=new MultiRoughTransDlg( _dictBox, result, this ); + dialog->exec(); + delete dialog; +} + +void CatalogManagerView::mailFiles() +{ + CatManListItem* item = (CatManListItem*)currentItem(); + if(item->isDir()) { + QStringList filesToSend; + QStringList childrenList = item->allChildrenList(true); + + QStringList::const_iterator it; + for (it = childrenList.constBegin(); it != childrenList.constEnd(); ++it) { + CatManListItem* i = _fileList[(*it)]; + if (i->hasPo()) { + filesToSend << i->poFile(); + } + } + mailer->sendFiles(filesToSend, item->text(0)); + } else { + if (item->hasPo()) { + mailer->sendOneFile(item->poFile()); + } + } +} + +void CatalogManagerView::mailMarkedFiles() +{ + if (_markerList.count() == 0) + return; + + QStringList filesToSend; + QStringList::const_iterator it; + for (it = _markerList.constBegin(); it != _markerList.constEnd(); ++it) { + CatManListItem* i = _fileList[(*it)]; + if (i->hasPo()) { + filesToSend << i->poFile(); + } + } + mailer->sendFiles(filesToSend); +} + +void CatalogManagerView::packageFiles( ) +{ + CatManListItem* item = (CatManListItem*)currentItem(); + if(item->isDir()) { + QStringList filesToPackage; + QStringList childrenList = item->allChildrenList(true); + + QStringList::const_iterator it; + for (it = childrenList.constBegin(); it != childrenList.constEnd(); ++it) { + CatManListItem* i = _fileList[(*it)]; + if (i->hasPo()) { + filesToPackage << i->poFile(); + } + } + QString packageFileName = KFileDialog::getSaveFileName(QString::null,"*.tar.bz2\n*.tar.gz",this); + mailer->buildArchive( filesToPackage, packageFileName, QString::null, false ); + } + else { + if (item->hasPo()) { + QStringList fileToPackage(item->poFile()); + QString packageFileName = KFileDialog::getSaveFileName(QString::null,"*.tar.bz2\n*.tar.gz",this); + mailer->buildArchive( fileToPackage, packageFileName, QString::null, false ); + } + } +} +void CatalogManagerView::packageMarkedFiles( ) +{ + if (_markerList.count() == 0) + return; + + QStringList filesToPackage; + QStringList::const_iterator it; + for (it = _markerList.constBegin(); it != _markerList.constEnd(); ++it) { + CatManListItem* i = _fileList[(*it)]; + if (i->hasPo()) { + filesToPackage << i->poFile(); + } + } + + QString packageFileName = KFileDialog::getSaveFileName(QString::null,"*.tar.bz2\n*.tar.gz",this); + mailer->buildArchive( filesToPackage, packageFileName, QString::null, false ); +} + +// CVS +void CatalogManagerView::cvsUpdate( ) +{ + doCVSCommand( CVS::Update ); +} + +void CatalogManagerView::cvsUpdateMarked( ) +{ + doCVSCommand( CVS::Update, true ); +} + +void CatalogManagerView::cvsCommit( ) +{ + doCVSCommand( CVS::Commit ); +} + +void CatalogManagerView::cvsCommitMarked( ) +{ + doCVSCommand( CVS::Commit, true ); +} + +void CatalogManagerView::cvsStatus( ) +{ + doCVSCommand( CVS::Status ); +} + +void CatalogManagerView::cvsStatusMarked( ) +{ + doCVSCommand( CVS::Status, true ); +} + +void CatalogManagerView::cvsUpdateTemplate( ) +{ + doCVSCommand( CVS::Update, false, true ); +} + +void CatalogManagerView::cvsUpdateMarkedTemplate( ) +{ + doCVSCommand( CVS::Update, true, true ); +} + +void CatalogManagerView::cvsCommitTemplate( ) +{ + doCVSCommand( CVS::Commit, false, true ); +} + +void CatalogManagerView::cvsCommitMarkedTemplate( ) +{ + doCVSCommand( CVS::Commit, true, true ); +} + +void CatalogManagerView::cvsDiff( ) +{ + doCVSCommand( CVS::Diff, false, false ); +} + +void CatalogManagerView::doCVSCommand( CVS::Command cmd, bool marked, bool templates ) +{ + KSharedConfig* config = _project->sharedConfig(); + if ( marked ) { + if ( _markerList.isEmpty() ) return; + QStringList fileList; + QStringList::const_iterator it; + for ( it = _markerList.constBegin( ); it != _markerList.constEnd( ); ++it ) { + CatManListItem * i = _fileList[(*it)]; + if ( templates && i->hasPot( ) ) + fileList << i->potFile( ); + else if ( !templates && i->hasPo( ) ) + fileList << i->poFile( ); + } + cvshandler->execCVSCommand( this, cmd, fileList, templates, config ); + } else { + const QString basedir = ( templates ? _settings.potBaseDir : _settings.poBaseDir ); + QString cvsItem; + CatManListItem * item = (CatManListItem*)currentItem( ); + if ( ( cmd == CVS::Commit || cmd == CVS::Diff ) && item->isDir( ) ) { + // all children including directories + QStringList cvsItems = item->allChildrenFileList (true, false, true); + if ( !cvsItems.isEmpty( ) ) + cvshandler->execCVSCommand( this, cmd, cvsItems, templates, config ); + } else { + if ( templates && item->hasPot( ) ) + cvsItem = item->potFile( ); + else if ( !templates && item->hasPo( ) ) + cvsItem = item->poFile( ); + + if ( !cvsItem.isEmpty( ) ) + cvshandler->execCVSCommand( this, cmd, cvsItem, templates, config ); + } + } +} + +//SVN +void CatalogManagerView::svnUpdate( ) +{ + doSVNCommand( SVN::Update ); +} + +void CatalogManagerView::svnUpdateMarked( ) +{ + doSVNCommand( SVN::Update, true ); +} + +void CatalogManagerView::svnCommit( ) +{ + doSVNCommand( SVN::Commit ); +} + +void CatalogManagerView::svnCommitMarked( ) +{ + doSVNCommand( SVN::Commit, true ); +} + +void CatalogManagerView::svnStatusRemote( ) +{ + doSVNCommand( SVN::StatusRemote ); +} + +void CatalogManagerView::svnStatusRemoteMarked( ) +{ + doSVNCommand( SVN::StatusRemote, true ); +} + +void CatalogManagerView::svnStatusLocal( ) +{ + doSVNCommand( SVN::StatusLocal ); +} + +void CatalogManagerView::svnStatusLocalMarked( ) +{ + doSVNCommand( SVN::StatusLocal, true ); +} + +void CatalogManagerView::svnInfo() +{ + doSVNCommand( SVN::Info ); +} + +void CatalogManagerView::svnInfoMarked() +{ + doSVNCommand( SVN::Info, true ); +} + +void CatalogManagerView::svnUpdateTemplate( ) +{ + doSVNCommand( SVN::Update, false, true ); +} + +void CatalogManagerView::svnUpdateMarkedTemplate( ) +{ + doSVNCommand( SVN::Update, true, true ); +} + +void CatalogManagerView::svnCommitTemplate( ) +{ + doSVNCommand( SVN::Commit, false, true ); +} + +void CatalogManagerView::svnCommitMarkedTemplate( ) +{ + doSVNCommand( SVN::Commit, true, true ); +} + +void CatalogManagerView::svnDiff( ) +{ + doSVNCommand( SVN::Diff, false, false ); +} + +void CatalogManagerView::doSVNCommand( SVN::Command cmd, bool marked, bool templates ) +{ + KSharedConfig* config = _project->sharedConfig(); + if ( marked ) { + if ( _markerList.isEmpty() ) return; + QStringList fileList; + QStringList::const_iterator it; + for ( it = _markerList.constBegin( ); it != _markerList.constEnd( ); ++it ) { + CatManListItem * i = _fileList[(*it)]; + if ( templates && i->hasPot( ) ) + fileList << i->potFile( ); + else if ( !templates && i->hasPo( ) ) + fileList << i->poFile( ); + } + svnhandler->execSVNCommand( this, cmd, fileList, templates, config ); + } else { + const QString basedir = ( templates ? _settings.potBaseDir : _settings.poBaseDir ); + QString svnItem; + CatManListItem * item = (CatManListItem*)currentItem( ); + if ( ( cmd == SVN::Commit || cmd == SVN::Diff ) && item->isDir( ) ) { + // all children including directories + QStringList svnItems = item->allChildrenFileList (true, false, true); + if ( !svnItems.isEmpty( ) ) + svnhandler->execSVNCommand( this, cmd, svnItems, templates, config ); + } else { + if ( templates && item->hasPot( ) ) + svnItem = item->potFile( ); + else if ( !templates && item->hasPo( ) ) + svnItem = item->poFile( ); + + if ( !svnItem.isEmpty( ) ) + svnhandler->execSVNCommand( this, cmd, svnItem, templates, config ); + } + } +} + +void CatalogManagerView::showLog() +{ + _logWindow->show(); +} + +QString CatalogManagerView::find( FindOptions &options, QStringList &rest ) +{ + CatManListItem* i=(CatManListItem*) currentItem(); + + if(!i || options.inAllFiles) + i=(CatManListItem*)_dirList["/"]; + + QValueList<QString> foundFiles; + _stopSearch = false; + + const QString search = options.findStr.lower().simplifyWhiteSpace(); + QStringList searchWords = QStringList::split(' ', search); + + QStringList childrenList; + if( i->isFile() ) childrenList.append(i->name()); + else childrenList =i->allChildrenList(true); + + emit prepareFindProgressBar(childrenList.size()); + + QStringList::const_iterator it; + for( it = childrenList.constBegin(); it != childrenList.constEnd(); ++it ) + { + CatManListItem* item = _fileList[(*it)]; + + if( !item ) + { + kdWarning(KBABEL_CATMAN) << "The file information not found, skipping" << endl; + continue; + } + + // skip if not marked and we lookup in marked + if( options.inMarkedFiles && !item->marked() ) + { + kdDebug(KBABEL_CATMAN) << "Skipping due marking " << item->name() << endl; + emit signalSearchedFile(1); + continue; + } + + bool doSearch = options.isRegExp || options.inTemplates; // for regexp and templates we do not support index search + if( item->wordsUpdated() ) + doSearch = doSearch || hasMatchingWords(item->wordList(), searchWords); + else doSearch = true; // we do not have index, we need to search + if( doSearch ) + { + QString itemFile; + if( options.inTemplates ) + { + if( item->hasPot() ) itemFile=item->potFile(); + } else { + if( item->hasPo() ) itemFile=item->poFile(); + } + + if( itemFile.isNull() ) + { + emit signalSearchedFile(1); + continue; + } + + if( PoInfo::findInFile( itemFile , options ) ) + { + emit signalSearchedFile(1); + rest.clear(); + if( _stopSearch ) + { + // if we are stopped, return what we found and clear the rest + _stopSearch = false; + return itemFile; + } + const QString foundItemFile = itemFile; + + it++; + while( it != childrenList.constEnd() ) + { + CatManListItem *item = _fileList[(*it)]; + + itemFile = QString::null; + if( options.inTemplates ) + { + if( item->hasPot() ) itemFile=item->potFile(); + } else { + if( item->hasPo() )itemFile=item->poFile(); + } + if( options.inMarkedFiles && !item->marked() ) + itemFile=QString::null; + + if( !itemFile.isNull()) + { + if( item->wordsUpdated() && !options.inTemplates ) + { + if( options.isRegExp || hasMatchingWords(item->wordList(), searchWords) ) + { + rest.append( itemFile ); + } + else kdDebug(KBABEL_CATMAN) << "Don't try to lookup in " << itemFile << endl; + } else { + rest.append( itemFile ); // there is no word index, add the file + } + } else emit signalSearchedFile(1); + + it++; + } + return foundItemFile; + + } + } else kdDebug(KBABEL_CATMAN) << "Skipping " << item->poFile() << endl; + emit signalSearchedFile(1); + if( _stop || _stopSearch ) { + _stopSearch = false; + rest.clear(); + if( _updateNesting == 0 && !_stop ) emit updateFinished(); + return QString::null; + } + } + return QString::null; +} + +bool CatalogManagerView::hasMatchingWords( QStringList &itemWords, QStringList &searchWords) +{ + for( QStringList::const_iterator it1 = searchWords.constBegin() ; it1 != searchWords.constEnd() ; ++it1 ) + for( QStringList::const_iterator it2 = itemWords.constBegin() ; it2 != itemWords.constEnd() ; ++it2 ) + if( *it1 == *it2 + || (*it1).contains(*it2) + || (*it2).contains(*it1) ) return true; + return false; +} + +void CatalogManagerView::showContentsMenu(QListViewItem *i, const QPoint &point, int) +{ + CatManListItem* item = (CatManListItem*) i; + + if(!item) + return; + + if(item->isDir()) + { + _dirContentsMenu->exec(point); + } + else + { + _fileContentsMenu->exec(point); + } +} + +void CatalogManagerView::checkSelected() +{ + CatManListItem* item=(CatManListItem*)selectedItem(); + if(!item) return; + + const uint actionValue = + NEEDS_PO * item->hasPo() + NEEDS_POT * item->hasPot() + + NEEDS_MARK * item->marked() + NEEDS_DIR * item->isDir() + + NEEDS_PO_CVS * m_validPOCVSRepository + NEEDS_POT_CVS * m_validPOTCVSRepository + + NEEDS_PO_SVN * m_validPOSVNRepository + NEEDS_POT_SVN * m_validPOTSVNRepository; + + emit selectedChanged(actionValue); +} + +void CatalogManagerView::activateItem(QListViewItem *) +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + if(!item) + return; + + if(item->isDir()) + { + item->setOpen(!item->isOpen()); + return; + } + + if(item->hasPo()) + { + emit openFile(item->poFile(),item->package()); + } + else if(item->hasPot()) + { + emit openTemplate(item->potFile(),item->poFile(),item->package()); + } + else + { + kdError(KBABEL_CATMAN) << "CatalogManagerView::activateItem: item has no file?" << endl; + } + +} + +void CatalogManagerView::slotOpenFile() +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + if(item && item->isFile()) + { + activateItem(item); + } +} + +void CatalogManagerView::slotOpenFileInNewWindow() +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + if(item && item->isFile()) + { + QString filename; + if(item->hasPo()) + { + emit openFileInNewWindow(item->poFile(),item->package()); + } + else if(item->hasPot()) + { + emit openTemplateInNewWindow(item->potFile(),item->poFile(),item->package()); + } + } +} + +void CatalogManagerView::slotOpenTemplate() +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + if(item && item->isFile()) + { + emit openFile(item->potFile(),item->package()); + } +} + +void CatalogManagerView::slotDeleteFile() +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + if(item && item->isFile() && item->hasPo() && !item->hasPot()) + { + const QString msg=i18n("Do you really want to delete the file %1?").arg(item->poFile()); + if(KMessageBox::warningContinueCancel(this,msg,i18n("Warning"),KGuiItem( i18n("Delete"), "editdelete"))== KMessageBox::Continue) + { + if(!QFile::remove(item->poFile())) + { + KMessageBox::sorry(this,i18n("Was not able to delete the file %1!").arg(item->poFile())); + } + } + } +} + +void CatalogManagerView::toggleMark() +{ + CatManListItem* i = (CatManListItem*) currentItem(); + if( i && i->isDir() ) slotToggleMarksInDir(); + else slotToggleMark(); +} + +void CatalogManagerView::slotToggleMark() +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + if(item && item->isFile()) + { + bool wasMarked=item->marked(); + item->setMarked(!wasMarked); + + if(wasMarked) + { + _markerList.remove(item->package()); + } + else + { + _markerList.append(item->package()); + } + } + + checkSelected(); +} + +void CatalogManagerView::slotToggleMarksInDir() +{ + CatManListItem* i=(CatManListItem*) currentItem(); + + if(i && i->isDir()) + { + const QStringList contentList = i->allChildrenList(true); + + QStringList::const_iterator it; + for( it = contentList.constBegin(); it != contentList.constEnd(); ++it ) + { + CatManListItem* item = _fileList[(*it)]; + + if ( item == 0 ) + kdFatal(KBABEL_CATMAN) << "CatalogManagerView::slotToggleMarkInDir: item not in list" << endl; + + const bool wasMarked=item->marked(); + item->setMarked(!wasMarked); + + if(wasMarked) + { + _markerList.remove(item->package()); + } + else + { + _markerList.append(item->package()); + } + } + } + + checkSelected(); +} + + +void CatalogManagerView::slotClearMarksInDir() +{ + CatManListItem* i=(CatManListItem*) currentItem(); + + if(i && i->isDir()) + { + const QStringList contentList=i->contentsList(true); + + QStringList::const_iterator it; + for( it = contentList.constBegin(); it != contentList.constEnd(); ++it ) + { + CatManListItem* item = _fileList[(*it)]; + + if ( item == 0 ) + kdFatal(KBABEL_CATMAN) << "CatalogManagerView::slotClearMarkInDir: item not in list" << endl; + + if(item->marked()) + { + _markerList.remove(item->package()); + } + item->setMarked(false); + } + } + + checkSelected(); +} + + +void CatalogManagerView::slotDirCommand(int index) +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + + if(index>=0 && item && item->isDir()) + { + QString cmd=*(_settings.dirCommands).at(index); + cmd.replace("@PACKAGE@",item->name()); + cmd.replace("@PODIR@",item->poFile()); + cmd.replace("@POTDIR@",item->potFile()); + cmd.replace("@POFILES@",current().join(" ")); + cmd.replace("@MARKEDPOFILES@",marked().join(" ")); + + kdDebug(KBABEL_CATMAN) << cmd << endl; + + KProcess* proc = new KShellProcess(); + _pendingProcesses.append(proc); + + connect( proc,SIGNAL( processExited(KProcess *) ), this + ,SLOT( processEnded(KProcess*) ) ); + connect( proc,SIGNAL( receivedStdout(KProcess*,char*,int) ), this + ,SLOT( showOutput(KProcess*,char*,int) ) ); + connect( proc,SIGNAL( receivedStderr(KProcess*,char*,int) ), this + ,SLOT( showOutput(KProcess*,char*,int) ) ); + + *proc << "cd" << item->poFile() << ";" << cmd; + proc->start(KProcess::NotifyOnExit,KProcess::AllOutput); + } +} + +void CatalogManagerView::slotFileCommand(int index) +{ + CatManListItem* item=(CatManListItem*) currentItem(); + + if(index>=0 && item && item->isFile()) + { + CatManListItem* parent = (CatManListItem*)item->parent(); + + QString cmd=*(_settings.fileCommands).at(index); + cmd.replace("@PACKAGE@",item->name()); + cmd.replace("@POFILE@",item->poFile()); + cmd.replace("@POTFILE@",item->potFile()); + cmd.replace("@PODIR@",parent->poFile()); + cmd.replace("@POTDIR@",parent->potFile()); + cmd.replace("@POEMAIL@",item->text(COL_TRANSLATOR)); + + kdDebug(KBABEL_CATMAN) << cmd << endl; + + KProcess* proc = new KShellProcess(); + _pendingProcesses.append(proc); + + connect( proc,SIGNAL( processExited(KProcess *) ), this + ,SLOT( processEnded(KProcess*) ) ); + connect( proc,SIGNAL( receivedStdout(KProcess*,char*,int) ), this + ,SLOT( showOutput(KProcess*,char*,int) ) ); + connect( proc,SIGNAL( receivedStderr(KProcess*,char*,int) ), this + ,SLOT( showOutput(KProcess*,char*,int) ) ); + + *proc << "cd" << parent->poFile() << ";" << cmd; + proc->start(KProcess::NotifyOnExit,KProcess::AllOutput); + } + +} + + +void CatalogManagerView::updateFile(QString fileWithPath, bool force) +{ + QString relFile; + if(fileWithPath.startsWith(_settings.poBaseDir)) + { + relFile=fileWithPath.mid(_settings.poBaseDir.length()); + } + else if(fileWithPath.startsWith(_settings.potBaseDir)) + { + relFile=fileWithPath.mid(_settings.potBaseDir.length()); + } + else + { + return; + } + + if(relFile.endsWith(".pot")) + { + relFile.truncate(relFile.length()-4); + } + else if(relFile.endsWith(".po")) + { + relFile.truncate(relFile.length()-3); + } + + CatManListItem* item=_fileList[relFile]; + + if(item) + { + _updateNesting++; + if( force ) item->forceUpdate(); + else item->checkUpdate(); + _updateNesting--; + } + +} + +void CatalogManagerView::updateAfterSave(QString fileWithPath, PoInfo &newInfo) +{ + QString relFile; + if(fileWithPath.startsWith(_settings.poBaseDir)) + { + relFile=fileWithPath.mid(_settings.poBaseDir.length()); + } + else if(fileWithPath.startsWith(_settings.potBaseDir)) + { + relFile=fileWithPath.mid(_settings.potBaseDir.length()); + } + else + { + return; + } + + if(relFile.endsWith(".pot")) + { + relFile.truncate(relFile.length()-4); + } + else if(relFile.endsWith(".po")) + { + relFile.truncate(relFile.length()-3); + } + + CatManListItem* item=_fileList[relFile]; + + if(item) + { + item->updateAfterSave(newInfo); + } + +} + +void CatalogManagerView::buildTree() +{ + // in case we were called after settings update + disconnect( this, SIGNAL( updateFinished() ), this, SLOT(buildTree() ) ); + + emit signalBuildTree(false); // announce start of building + + clear(); + + if(isActive()) + return; + + _updateNesting++; + + _active=true; + _stop=false; + + + CatManListItem* root = new CatManListItem(this, this,_settings.poBaseDir,_settings.potBaseDir); + _dirList.insert("/",root); + //root->setSelectable(false); + + QFileInfo fileInfo(_settings.poBaseDir); + if(!fileInfo.isDir()) + { + KMessageBox::error(this,i18n("You have not specified a valid folder " +"for the base folder of the PO files:\n%1\n" +"Please check your settings in the project settings dialog.").arg(_settings.poBaseDir)); + + _active=false; + _updateNesting--; + if( _updateNesting == 0 ) emit updateFinished(); + return; + } + + cvshandler->setPOBaseDir( _settings.poBaseDir ); + svnhandler->setPOBaseDir( _settings.poBaseDir ); + mailer->setPOBaseDir(_settings.poBaseDir); + + fileInfo.setFile(_settings.potBaseDir); + if(!fileInfo.isDir() && !_settings.potBaseDir.isEmpty()) + { + KMessageBox::error(this,i18n("You have not specified a valid folder " +"for the base folder of the PO template files:\n%1\n" +"Please check your settings in the project settings dialog.").arg(_settings.potBaseDir)); + } + + cvshandler->setPOTBaseDir( _settings.potBaseDir ); + svnhandler->setPOTBaseDir( _settings.potBaseDir ); + + setCursor(KCursor::waitCursor()); + + //"/" is the root item + buildDir("/",true); // build dir without updating the items... + + if( _stop ) { + _active = false; + _updateNesting--; + if( _updateNesting == 0 ) emit updateFinished(); + return; + } + + _dirWatch->addDir(_settings.poBaseDir); + if(!_settings.potBaseDir.isEmpty()) + _dirWatch->addDir(_settings.potBaseDir); + + emit signalBuildTree(true); // announce beginning of tree building + + unsetCursor(); + + if( _stop ) { + _active = false; + _updateNesting--; + if( _updateNesting == 0 ) emit updateFinished(); + return; + } + + updateMarkerList(); + + const int files=_fileList.count()+_dirList.count(); + + _readInfoCount = 0; + + emit prepareProgressBar(i18n("Reading file information"),files); + + root->setOpen(true); + + if( _stop ) { + _active = false; + _updateNesting--; + if( _updateNesting == 0 ) emit updateFinished(); + return; + } + + // first read information about the files... + QDictIterator<CatManListItem> it( _fileList ); // iterator for dict + + int i=0; + while ( it.current() && !_stop) + { + it.current()->checkUpdate(true); + ++i; + ++it; + } + + // ...then update directories + QDictIterator<CatManListItem> dit( _dirList ); // iterator for dict + + while ( dit.current() && !_stop) + { + dit.current()->checkUpdate(); + ++i; + ++dit; + } + + emit clearProgressBar(); + + _dirWatch->startScan(); + pause(false); + + _active=false; + + _updateNesting--; + + if( _updateNesting == 0 ) + { + emit updateFinished(); + } +} + +bool CatalogManagerView::buildDir(QString relDir,bool fast) +{ + if( _stop ) return false; + + bool haveTemplateDir=true; + QFileInfo fileInfo; + + fileInfo.setFile(_settings.potBaseDir); + if(!fileInfo.isDir()) + { + haveTemplateDir=false; + } + + bool potHasFiles=false; + if(haveTemplateDir) + potHasFiles=buildDir(_settings.potBaseDir,relDir,".pot",fast); + + bool poHasFiles=buildDir(_settings.poBaseDir,relDir,".po",fast); + + return (poHasFiles | potHasFiles); +} + + +bool CatalogManagerView::buildDir(const QString& baseDir,const QString& relDir + , const QString extension , bool fast) +{ + if( _stop ) return false; + + bool havePoFiles=false; + + CatManListItem* thisItem=_dirList[relDir]; + if(!thisItem) + { + kdFatal(KBABEL_CATMAN) << "null pointer to this item" << endl; + return false; + } + + const QString poBaseDir=_settings.poBaseDir; + const QString potBaseDir=_settings.potBaseDir; + + // traverse directory in poBaseDir + QDir dir(baseDir+relDir); + QStringList entryList=dir.entryList("*"+extension,QDir::Files,QDir::Name); + + QStringList::const_iterator it; + + for ( it = entryList.constBegin(); it != entryList.constEnd() && !_stop ; ++it ) + { + if( _stop ) return false; + + havePoFiles=true; + + QString file=relDir+(*it); + file.remove(QRegExp(extension+"$")); + CatManListItem* item = _fileList[file]; + if(!item) + { + item = new CatManListItem(this,thisItem,poBaseDir+file+".po",potBaseDir+file+".pot",file); + _fileList.insert(file,item); + _readInfoFileList.prepend(file); + + if(_markerList.contains(file)) + { + item->setMarked(true); + } + + if(!fast) + { + item->checkUpdate(); + } + } + } + + entryList=dir.entryList(QDir::Dirs,QDir::Name); + + for ( it = entryList.constBegin(); it != entryList.constEnd() && !_stop ; ++it ) + { + if( _stop ) return false; + + if((*it)=="." || (*it)=="..") + { + continue; + } + + QString subDir=relDir+(*it)+"/"; + if(!_dirWatch->contains(baseDir+subDir)) + { + _dirWatch->addDir(baseDir+subDir); + } + + bool otherHasFiles=true; + + CatManListItem* item = _dirList[subDir]; + if(!item && !_stop) + { + item = new CatManListItem(this, thisItem,poBaseDir+subDir,potBaseDir+subDir,subDir); + _dirList.insert(subDir,item); + + otherHasFiles=false; + } + + if( _stop ) return false; + + // recursive call + if(!buildDir(baseDir,subDir,extension,fast) && !otherHasFiles) + { + kdDebug(KBABEL_CATMAN) << "skipping " << subDir << endl; + deleteDirItem(subDir); + item=0; + } + else + havePoFiles=true; + + } // end looking up directories in po base dir + + return havePoFiles; +} + + +void CatalogManagerView::updateDir(QString relDir) +{ + if( _stop ) return; + + kdDebug(KBABEL_CATMAN) << "updating dir " << relDir << endl; + + bool havePoFiles=false; + + CatManListItem* thisItem=_dirList[relDir]; + if(!thisItem) + { + kdFatal(KBABEL_CATMAN) << "null pointer to this item" << endl; + return; + } + + QStringList contentList = thisItem->contentsList(true); + + const QString poBaseDir=_settings.poBaseDir; + const QString potBaseDir=_settings.potBaseDir; + + // first lookup template directory + QDir dir(potBaseDir+relDir); + QStringList entryList=dir.entryList("*.pot",QDir::Files,QDir::Name); + + QStringList::const_iterator it; + + for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it ) + { + if( _stop ) return; + + havePoFiles=true; + + QString file=relDir+(*it); + file.remove(QRegExp(".pot$")); + CatManListItem* item = _fileList[file]; + if(!item) + { + item = new CatManListItem(this, thisItem,poBaseDir+file+".po",potBaseDir+file+".pot",file); + _fileList.insert(file,item); + + if(_markerList.contains(file)) + { + item->setMarked(true); + } + + item->checkUpdate(); + } + else + { + item->checkUpdate(); + } + + contentList.remove(file); + } + + entryList=dir.entryList(QDir::Dirs,QDir::Name); + + for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it ) + { + if( _stop ) return; + + if((*it)=="." || (*it)=="..") + { + continue; + } + + bool newDirAdded=false; + + QString subDir=relDir+(*it)+"/"; + if(!_dirWatch->contains(potBaseDir+subDir)) + { + _dirWatch->addDir(potBaseDir+subDir); + + newDirAdded=true; + } + + CatManListItem* item = _dirList[subDir]; + if(!item && newDirAdded) + { + item = new CatManListItem(this, thisItem,poBaseDir+subDir,potBaseDir+subDir,subDir); + _dirList.insert(subDir,item); + + if(!buildDir(subDir,false)) + { + kdDebug(KBABEL_CATMAN) << "skipping " << subDir << endl; + deleteDirItem(subDir); + item=0; + } + } + else if(newDirAdded) + { + updateDir(subDir); + } + + + // if directory was already here, but no item + // -> directory contains no files + if(item && !newDirAdded) + { + havePoFiles=true; + } + + } // end looking up directories in template dir + + // now traverse directory in poBaseDir + dir.setPath(poBaseDir+relDir); + entryList=dir.entryList("*.po",QDir::Files,QDir::Name); + + for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it ) + { + havePoFiles=true; + + if( _stop ) return; + + QString file=relDir+(*it); + file.remove(QRegExp(".po$")); + CatManListItem* item = _fileList[file]; + if(!item) + { + item = new CatManListItem(this, thisItem,poBaseDir+file+".po",potBaseDir+file+".pot",file); + _fileList.insert(file,item); + + if(_markerList.contains(file)) + { + item->setMarked(true); + } + + item->checkUpdate(); + } + else + { + item->checkUpdate(); + } + + contentList.remove(file); + } + + entryList=dir.entryList(QDir::Dirs,QDir::Name); + + for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it ) + { + if( _stop ) return; + + if((*it)=="." || (*it)=="..") + { + continue; + } + + bool newDirAdded=false; + + QString subDir=relDir+(*it)+"/"; + if(!_dirWatch->contains(poBaseDir+subDir)) + { + _dirWatch->addDir(poBaseDir+subDir); + newDirAdded=true; + } + + CatManListItem* item = _dirList[subDir]; + + bool templateHasFiles=(bool)item; + + if(!item && newDirAdded) + { + item = new CatManListItem(this, thisItem,poBaseDir+subDir,potBaseDir+subDir,subDir); + _dirList.insert(subDir,item); + + if(!buildDir(subDir,false) && !templateHasFiles) + { + kdDebug(KBABEL_CATMAN) << "skipping " << subDir << endl; + deleteDirItem(subDir); + item=0; + } + } + else if(newDirAdded) + { + updateDir(subDir); + } + + // if directory was already here, but no item + // -> directory contains no files + if(item && !newDirAdded) + { + havePoFiles=true; + } + + + } // end looking up directories in po base dir + + + // check, if something in the directory has been deleted + // but only if we traversed also the template directory + if(contentList.count()>0) + { + QStringList::const_iterator it; + for( it = contentList.constBegin(); it != contentList.constEnd(); ++it ) + { + QFileInfo po(poBaseDir+(*it)); + QFileInfo pot(potBaseDir+(*it)); + + if(!po.exists() && !pot.exists()) + { + CatManListItem* item = _fileList[(*it)]; + if(item) + { + if(item->marked()) + _markerList.remove(item->package()); + + _fileList.remove((*it)); + delete item; + } + } + } + } + + if(!havePoFiles) + { + deleteDirItem(relDir); + + // if this directory has to be removed, check, if + // the parent directory has to be removed too + const int index=relDir.findRev("/",relDir.length()-2); + if(index<0) + { + relDir="/"; + } + relDir=relDir.left(index+1); + updateDir(relDir); + } +} + +void CatalogManagerView::directoryChanged(const QString& dir) +{ + pause(true); + + QString relDir, relDirPo, relDirPot; + if(dir.startsWith(_settings.poBaseDir)) + { + relDirPo=dir.mid(_settings.poBaseDir.length()); + } + if(dir.startsWith(_settings.potBaseDir)) + { + relDirPot=dir.mid(_settings.potBaseDir.length()); + } + + if( relDirPo.isEmpty() ) + { + // use POT + relDir = relDirPot; + } + else if( relDirPot.isEmpty() ) + { + // use PO + relDir = relDirPo; + } + else + { + // both PO and POT usable, find out the correct one + if( relDirPo.left(1) == "/" ) + { + relDir = relDirPo; + } + else + { + relDir = relDirPot; + } + } + + if(relDir.right(1)!="/") + { + relDir+="/"; + } + + kdDebug(KBABEL_CATMAN) << "directory changed: " << relDir << endl; + + QFileInfo fileInfo(_settings.potBaseDir); + + CatManListItem* thisItem=_dirList[relDir]; + if(!thisItem) + { + // if this item is not in the list search for next existing parent item + QString prevRelDir; + do + { + prevRelDir=relDir; + const int index=relDir.findRev("/",relDir.length()-2); + if(index<0) + { + relDir="/"; + } + relDir=relDir.left(index+1); + + thisItem=_dirList[relDir]; + } + while(relDir!="/" && !thisItem); + + if(!thisItem) + { + kdFatal(KBABEL_CATMAN) << "null pointer to this item: " << relDir << endl; + return; + } + else + { + // if a parent item dir is found, create the needed item in this dir + // and build the tree from this item on + kdDebug(KBABEL_CATMAN) << "building dir: " << prevRelDir << endl; + CatManListItem* item = new CatManListItem(this, thisItem,_settings.poBaseDir+prevRelDir + ,_settings.potBaseDir+prevRelDir,prevRelDir); + _dirList.insert(prevRelDir,item); + + + if(!buildDir(prevRelDir,false)) + { + deleteDirItem(prevRelDir); + } + } + } + else + { + updateDir(relDir); + } + + pause(false); +} + + +void CatalogManagerView::directoryDeleted(const QString& dir) +{ + pause(true); + + QString relDir, relDirPo, relDirPot; + if(dir.startsWith(_settings.poBaseDir)) + { + relDirPo=dir.mid(_settings.poBaseDir.length()); + } + if(dir.startsWith(_settings.potBaseDir)) + { + relDirPot=dir.mid(_settings.potBaseDir.length()); + } + + if( relDirPo.isEmpty() ) + { + // use POT + relDir = relDirPot; + } + else if( relDirPot.isEmpty() ) + { + // use PO + relDir = relDirPo; + } + else + { + // both PO and POT usable, find out the correct one + if( relDirPo.left(1) == "/" ) + { + relDir = relDirPo; + } + else + { + relDir = relDirPot; + } + } + + if(relDir.right(1)!="/") + { + relDir+="/"; + } + + kdDebug(KBABEL_CATMAN) << "directory deleted: " << relDir << endl; + + CatManListItem* thisItem=_dirList[relDir]; + if(thisItem) + { + // we have to take care, if one directory still exists + const bool poDeleted=!thisItem->hasPo(); + const bool potDeleted=!thisItem->hasPot(); + + // if neither the po- nor the pot-directory exists any more + // delete all sub items + if(poDeleted && potDeleted) + { + deleteDirItem(relDir); + } + else + { + QStringList childList = thisItem->contentsList(); + + CatManListItem* item; + QStringList::const_iterator it; + for( it = childList.constBegin();it != childList.constEnd(); ++it ) + { + item=_fileList[(*it)]; + if(item) + { + if( (poDeleted && !item->hasPot()) || + (potDeleted && !item->hasPo()) ) + { + _fileList.remove((*it)); + delete item; + } + else + { + item->checkUpdate(); + } + } + else + { + item=_dirList[(*it)]; + if(item) + { + if( (poDeleted && !item->hasPot()) || + (potDeleted && !item->hasPo()) ) + { + deleteDirItem((*it)); + } + } + else + { + kdDebug(KBABEL_CATMAN) << "directoryDeleted: don't have item " + << (*it) << endl; + } + } + } + } + } + + pause(false); +} + +void CatalogManagerView::fileInfoRead( QString filename ) +{ + if( _readInfoFileList.find( filename ) != _readInfoFileList.end() ) { + emit progress( ++_readInfoCount); + _readInfoFileList.remove( filename ); + } + + if( _readInfoFileList.isEmpty() ) emit clearProgressBar(); +} + +void CatalogManagerView::setSettings(CatManSettings newSettings) +{ + CatManSettings oldSettings=_settings; + _settings=newSettings; + + if(_settings.poBaseDir.right(1)=="/") + _settings.poBaseDir.truncate(_settings.poBaseDir.length()-1); + if(_settings.potBaseDir.right(1)=="/") + _settings.potBaseDir.truncate(_settings.potBaseDir.length()-1); + + _dirCommandsMenu->clear(); + int counter=0; + for ( QStringList::const_iterator it = _settings.dirCommandNames.constBegin() + ; it != _settings.dirCommandNames.constEnd(); ++it ) + { + _dirCommandsMenu->insertItem((*it),counter); + counter++; + } + _dirCommandsMenu->insertSeparator(); + _dirCommandsMenu->insertItem(i18n("Log Window"),this,SLOT(showLog())); + + _fileCommandsMenu->clear(); + counter=0; + for ( QStringList::const_iterator it = _settings.fileCommandNames.constBegin() + ; it != _settings.fileCommandNames.constEnd(); ++it ) + { + _fileCommandsMenu->insertItem((*it),counter); + counter++; + } + _fileCommandsMenu->insertSeparator(); + _fileCommandsMenu->insertItem(i18n("Log Window"),this,SLOT(showLog())); + + const bool pathChanged = (oldSettings.poBaseDir!=_settings.poBaseDir) + || (oldSettings.potBaseDir!=_settings.potBaseDir); + + if(pathChanged) + { + if( !isActive() ) { + QTimer::singleShot(100,this,SLOT(buildTree())); + } else { + stop(); + connect( this, SIGNAL( updateFinished() ), this, SLOT(buildTree() ) ); + } + } + + toggleColumn( COL_MARKER, _settings.flagColumn ); + toggleColumn( COL_FUZZY, _settings.fuzzyColumn ); + toggleColumn( COL_UNTRANS, _settings.untranslatedColumn ); + toggleColumn( COL_TOTAL, _settings.totalColumn ); + // FIXME: follow CVS/SVN status + toggleColumn( COL_CVS_OR_SVN, _settings.cvsColumn ); + toggleColumn( COL_REVISION, _settings.revisionColumn ); + toggleColumn( COL_TRANSLATOR, _settings.translatorColumn ); +} + + +CatManSettings CatalogManagerView::settings() const +{ + return _settings; +} + + +void CatalogManagerView::hideEvent(QHideEvent*) +{ + pause(true); + + if(_dirWatch) + _dirWatch->stopScan(); +} + +void CatalogManagerView::showEvent(QShowEvent*) +{ + QTimer::singleShot(1,this,SLOT(checkUpdate())); + + pause(false); + + if(_dirWatch) + _dirWatch->startScan(true); +} + +void CatalogManagerView::contentsMousePressEvent(QMouseEvent* event) +{ + if(event->button() == LeftButton) + _pressPos=event->pos(); + + QListView::contentsMousePressEvent( event ); +} + +void CatalogManagerView::contentsMouseMoveEvent(QMouseEvent* event) +{ + if(event->state() & LeftButton) + { + const int delay = KGlobalSettings::dndEventDelay(); + if(QABS( event->pos().x() - _pressPos.x() ) >= delay || + QABS( event->pos().y() - _pressPos.y() ) >= delay) + { + CatManListItem* item = (CatManListItem*)itemAt(contentsToViewport(_pressPos)); + if(item && item->isFile()) + { + // always add the po-file and if existing the pot-file to the drag and + // let the user decide what to do, when dropping into kbabel + QStrList uri; + uri.append(QUriDrag::localFileToUri(item->poFile())); + if(item->hasPot()) + uri.append(QUriDrag::localFileToUri(item->potFile())); + + QUriDrag* drag = new QUriDrag(uri,this); + QPixmap icon=KGlobal::iconLoader()->loadIcon("txt",KIcon::Desktop); + drag->setPixmap(icon,QPoint(icon.width()/2,icon.height()/2)); + drag->drag(); + } + else + { + QListView::contentsMouseMoveEvent(event); + } + } + else + { + QListView::contentsMouseMoveEvent(event); + } + } + else + { + QListView::contentsMouseMoveEvent(event); + } +} + +void CatalogManagerView::readMarker( KConfig* config) +{ + KConfigGroupSaver cs(config,"CatalogManager"); + + _markerList = config->readListEntry("Marker"); +} + +void CatalogManagerView::saveMarker( KConfig* config) const +{ + KConfigGroupSaver cs(config,"CatalogManager"); + + config->writeEntry("Marker",_markerList); + config->sync(); +} + + +void CatalogManagerView::deleteDirItem(QString relDir) +{ + CatManListItem* thisItem=_dirList[relDir]; + + if(!thisItem) + return; + + _dirList.remove(relDir); + + QStringList childList = thisItem->allChildrenList(); + + QStringList::const_iterator it; + for( it = childList.constBegin();it != childList.constEnd(); ++it ) + { + if(!_fileList.remove((*it))) + _dirList.remove((*it)); + } + + + // delete the item with all sub item + delete thisItem; +} + + + +void CatalogManagerView::processEnded(KProcess* proc) +{ + _pendingProcesses.removeRef(proc); +} + + +void CatalogManagerView::showOutput(KProcess*, char *buffer, int buflen) +{ + const QCString output(buffer,buflen+1); + + _logView->insert(output); +} + +void CatalogManagerView::columnClicked(QListViewItem * item, const QPoint &, int c) +{ + if( item && c == COL_MARKER ) + { + slotToggleMark(); + } +} + +CatManListItem *CatalogManagerView::itemBelow( CatManListItem *item ) +{ + if( item->isDir() ) + { + if( item->firstChild() ) + return static_cast<CatManListItem *>( item->firstChild() ); + else + { + while( !static_cast<CatManListItem *>( item->nextSibling() ) ) + { + item = static_cast<CatManListItem *>( item->parent() ); + if( !item ) return item; + } + return static_cast<CatManListItem *>( item->nextSibling() ); + } + } + else + { + while( !static_cast<CatManListItem *>( item->nextSibling() ) ) + { + item = static_cast<CatManListItem *>( item->parent()); + if( !item ) return item; + } + return static_cast<CatManListItem *>( item->nextSibling() ); + } +} + +CatManListItem *CatalogManagerView::itemAbove( CatManListItem *item ) +{ + if( item->isDir() ) + { + if( item->firstChild() ) + return static_cast<CatManListItem *>( item->lastChild() ); + else + { + while( !static_cast<CatManListItem *>( item->previousSibling() ) ) + { + item = static_cast<CatManListItem *>( item->parent() ); + if( !item ) return item; + } + return static_cast<CatManListItem *>( item->previousSibling() ); + } + } + else + { + while( !static_cast<CatManListItem *>( item->previousSibling() ) ) + { + item = static_cast<CatManListItem *>( item->parent()); + if( !item ) return item; + } + return static_cast<CatManListItem *>( item->previousSibling() ); + } +} + +void CatalogManagerView::gotoNextUntranslated() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( ( i = itemBelow(current)) ) + { + if( i->untranslated() > 0 ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoPreviousUntranslated() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( (i = itemAbove(current)) ) + { + if( i->untranslated() > 0 ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoNextFuzzy() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( ( i = itemBelow(current)) ) + { + if( i->fuzzy() > 0 ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoPreviousFuzzy() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( (i = itemAbove(current)) ) + { + if( i->fuzzy() > 0 ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoNextFuzzyOrUntranslated() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( ( i = itemBelow(current)) ) + { + if( i->untranslated() > 0 || i->fuzzy() > 0 ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoPreviousFuzzyOrUntranslated() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( (i = itemAbove(current)) ) + { + if( i->untranslated() > 0 || i->fuzzy() > 0 ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoNextError() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( ( i = itemBelow(current)) ) + { + if( i->hasErrors() ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoPreviousError() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( (i = itemAbove(current)) ) + { + if( i->hasErrors() ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoNextTemplate() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( ( i = itemBelow(current)) ) + { + if( i->hasPot() && !i->hasPo() ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoPreviousTemplate() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( (i = itemAbove(current)) ) + { + if( i->hasPot() && !i->hasPo() ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoNextPo() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( ( i = itemBelow(current)) ) + { + if( i->hasPo() ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoPreviousPo() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( (i = itemAbove(current)) ) + { + if( i->hasPo() ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoNextMarked() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( ( i = itemBelow(current)) ) + { + if( i->marked() ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +void CatalogManagerView::gotoPreviousMarked() +{ + CatManListItem *i; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + while( (i = itemAbove(current)) ) + { + if( i->marked() ) + { + setCurrentItem(i); + ensureItemVisible(i); + return; + } else current = i; + } +} + +QStringList CatalogManagerView::current() +{ + QStringList result; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + if( current->isDir() ) + { + QStringList s = current->allChildrenList(true); + QStringList::const_iterator it; + for( it = s.constBegin() ; it != s.constEnd(); ++it ) + { + CatManListItem *item = _fileList[(*it)]; + result.append( item->poFile() ); + } + } + else + { + if( current->hasPo() ) result.append( current->poFile() ); + } + return result; +} + +QStringList CatalogManagerView::marked() +{ + QStringList result; + + QStringList::const_iterator it; + for( it = _markerList.constBegin() ; it != _markerList.constEnd(); ++it ) + { + CatManListItem *item = _fileList[(*it)]; + result.append( item->poFile() ); + } + return result; +} + +void CatalogManagerView::updateCurrent() +{ + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + if( !current->hasPo() && !current->hasPot() ) + { + if( current->isFile() ) + { + _fileList.remove(current->package()); + delete current; + } + else + { + directoryDeleted(current->package()); + } + } + else + { + if( current->isDir() ) + { + directoryChanged(current->poFile() ); + } + + // check, if the item didn't get lost by the update in directoryChanged() + CatManListItem *new_current = static_cast<CatManListItem *>(currentItem()); + if (new_current == current) + { + current->forceUpdate(); + } + } +} + +void CatalogManagerView::updateFiles( const QStringList& files ) +{ + QStringList::ConstIterator it; + for ( it = files.constBegin( ); it != files.constEnd( ); ++it ) { + updateFile( *it, true ); + } +} + +CVSHandler * CatalogManagerView::cvsHandler( ) +{ + return cvshandler; +} + +SVNHandler * CatalogManagerView::svnHandler( ) +{ + return svnhandler; +} + +void CatalogManagerView::validateUsingTool( const KDataToolInfo &tool, const QString& command ) +{ + QStringList result; + CatManListItem *current = static_cast<CatManListItem *>(currentItem()); + if( current->isDir() ) + { + const QStringList s = current->allChildrenList(true); + QStringList::const_iterator it; + for( it = s.constBegin() ; it != s.constEnd(); ++it ) + { + CatManListItem *item = _fileList[(*it)]; + if( item && item->hasPo() ) result.append( item->package() ); + } + } + else + { + result.append( current->package() ); + } + + validate_internal( result, tool, command ); +} + +void CatalogManagerView::validateMarkedUsingTool( const KDataToolInfo &tool, const QString& command ) +{ + validate_internal( _markerList, tool, command ); +} + +void CatalogManagerView::validate_internal( const QStringList& files, const KDataToolInfo &tool, const QString& ) +{ + if( files.isEmpty() ) return; + + KDataTool* t = tool.createTool(); + + if( !t ) + { + KMessageBox::error( this, i18n("Cannot instantiate a validation tool.\n" + "Please check your installation."), i18n("Validation Tool Error") ); + return; + } + + // setup options + if( !_validateOptionsDlg ) + { + _validateOptionsDlg = new KDialogBase( this, "validation options", + true, i18n("Validation Options"), KDialogBase::Ok|KDialogBase::Cancel); + _validateOptions = new ValidationOptions(_validateOptionsDlg); + _validateOptionsDlg->setMainWidget( _validateOptions ); + _validateOptions->resize( _validateOptions->sizeHint() ); + + // setup stored values + _validateOptions->markAsFuzzy->setChecked( _markAsFuzzy ); + _validateOptions->ignoreFuzzy->setChecked( _ignoreFuzzy ); + } + + if( _validateOptionsDlg->exec() != QDialog::Accepted ) + { + delete t; + + return; + } + + if( !_validateDialog ) + { + _validateDialog = new ValidateProgressDialog(_settings.ignoreURL, this); + connect( _validateDialog, SIGNAL( errorDoubleClicked(const QString,const int)), + this, SLOT(showError( const QString, const int ))); + } + + _markAsFuzzy = _validateOptions->markAsFuzzy->isChecked(); + _ignoreFuzzy = _validateOptions->ignoreFuzzy->isChecked(); + + _validateDialog->setMarkAsFuzzy(_markAsFuzzy); + _validateDialog->setIgnoreFuzzy(_ignoreFuzzy); + + QPtrList<CatManListItem> fileitems; + + for( QValueListConstIterator<QString> it=files.begin() ; it!=files.end() ; ++it ) + { + CatManListItem* item=_fileList[ (*it) ]; + if( item ) { + fileitems.append(item); + } else kdDebug(KBABEL_CATMAN) << "Cannot find the file item for " << (*it) << endl; + } + + _validateDialog->validate(tool, fileitems); + + delete t; +} + +void CatalogManagerView::showError( const QString package, const int num ) +{ + CatManListItem* item = _fileList[ package]; + if( !item ) + { + kdWarning() << "Can not find error package: " << package << endl; + return; + } + + emit gotoFileEntry( item->poFile(), package, num ); +} + +void CatalogManagerView::updateMarkerList() +{ + QStringList newMarkers; + + for( QStringList::const_iterator it = _markerList.constBegin(); it != _markerList.constEnd(); ++it ) { + if( _fileList[ (*it) ] ) + newMarkers.append( (*it) ); + } + + _markerList = newMarkers; +} + +void CatalogManagerView::slotValidPOCVSRepository( bool valid ) +{ + m_validPOCVSRepository = valid; + slotToggleCVSOrSVNColumn(valid); + // set initial state for CVS menu entries + emit selectedChanged(NEEDS_PO + NEEDS_PO_CVS * m_validPOCVSRepository); +} + +void CatalogManagerView::slotValidPOSVNRepository( bool valid ) +{ + m_validPOSVNRepository = valid; + slotToggleCVSOrSVNColumn(valid); + // set initial state for SVN menu entries + emit selectedChanged(NEEDS_PO + NEEDS_PO_SVN * m_validPOSVNRepository); +} + +void CatalogManagerView::slotValidPOTCVSRepository( bool valid ) +{ + m_validPOTCVSRepository = valid; + // set initial state for CVS menu entries + // ### TODO: something missing here? +} + +void CatalogManagerView::slotValidPOTSVNRepository( bool valid ) +{ + m_validPOTSVNRepository = valid; + // set initial state for SVN menu entries + // ### TODO: something missing here? +} + +void CatalogManagerView::slotToggleCVSOrSVNColumn( bool show ) +{ +#if 0 + toggleColumn( COL_CVS_OR_SVN, show ); +#else + // ### HACK + toggleColumn( COL_CVS_OR_SVN, m_validPOCVSRepository || m_validPOSVNRepository ); + +#endif +} + +void CatalogManagerView::toggleColumn( uint column, bool show ) +{ + if ( show ) { + setColumnWidthMode( column, Maximum ); + setColumnWidth( column, -1 ); + // ensure that the column heading is always fully visible + setColumnText( column, COLTEXT(column)); + } else { + setColumnWidthMode( column, Manual ); + setColumnWidth( column, 0 ); + } +} + +#include "catalogmanagerview.moc" +// kate: space-indent on; indent-width 4; replace-tabs on; |