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.
865 lines
41 KiB
865 lines
41 KiB
/***************************************************************************
|
|
* Copyright (C) 2004-2009 by Thomas Fischer *
|
|
* fischer@unix-ag.uni-kl.de *
|
|
* *
|
|
* 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., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
#include <cmath>
|
|
|
|
#include <tqlayout.h>
|
|
#include <tqlabel.h>
|
|
#include <tqprogressbar.h>
|
|
#include <tqtimer.h>
|
|
|
|
#include <tdelocale.h>
|
|
#include <kpushbutton.h>
|
|
#include <tdeapplication.h>
|
|
#include <tdemessagebox.h>
|
|
#include <ktextedit.h>
|
|
#include <tdelistview.h>
|
|
#include <tdeconfig.h>
|
|
#include <twin.h>
|
|
|
|
#include "macro.h"
|
|
#include "comment.h"
|
|
#include "preamble.h"
|
|
#include "macrowidget.h"
|
|
#include "entrywidget.h"
|
|
#include "preamblewidget.h"
|
|
#include "settings.h"
|
|
#include "fileexporterbibtex.h"
|
|
#include "mergeelements.h"
|
|
|
|
namespace KBibTeX
|
|
{
|
|
MergeElementsCliqueItem::MergeElementsCliqueItem( BibTeX::Entry* _entry, BibTeX::Macro* _macro, BibTeX::Preamble* _preamble, TQListView *parent )
|
|
: TQCheckListItem( parent, _entry == NULL ?( _macro == NULL ? _preamble->value()->text() : _macro->key() ) : _entry->id(), TQCheckListItem::CheckBox ), entry( _entry ), macro( _macro ), preamble( _preamble )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
void MergeElementsCliqueItem::stateChange( bool )
|
|
{
|
|
emit stateChanged( this );
|
|
};
|
|
|
|
MergeEntriesAlternativesController::MergeEntriesAlternativesController( const TQString &label, TQListView *parent )
|
|
: TQCheckListItem( parent, label, TQCheckListItem::RadioButtonController ), fieldType( BibTeX::EntryField::ftUnknown ), fieldName( label )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeEntriesAlternativesController::MergeEntriesAlternativesController( BibTeX::EntryField::FieldType _fieldType, TQListView *parent )
|
|
: TQCheckListItem( parent, BibTeX::EntryField::fieldTypeToString( _fieldType ), TQCheckListItem::RadioButtonController ), fieldType( _fieldType ), fieldName( BibTeX::EntryField::fieldTypeToString( _fieldType ) )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeMacrosAlternativesController::MergeMacrosAlternativesController( bool isKey, TQListView *parent )
|
|
: TQCheckListItem( parent, isKey ? i18n( "Key" ) : i18n( "Value" ), TQCheckListItem::RadioButtonController )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeEntriesAlternativesItem::MergeEntriesAlternativesItem( BibTeX::EntryField *_field, MergeEntriesAlternativesController *parent )
|
|
: TQCheckListItem( parent, _field->value()->text(), TQCheckListItem::RadioButton ), field( _field )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeMacrosAlternativesItem::MergeMacrosAlternativesItem( BibTeX::Value *_value, MergeMacrosAlternativesController *parent )
|
|
: TQCheckListItem( parent, _value->text(), TQCheckListItem::RadioButton ), value( _value )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeElementsAlternativesId::MergeElementsAlternativesId( const TQString & _id, MergeEntriesAlternativesController *parent ) : TQCheckListItem( parent, _id, TQCheckListItem::RadioButton ), id( _id )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeMacroAlternativesKey::MergeMacroAlternativesKey( const TQString & _key, MergeMacrosAlternativesController *parent ) : TQCheckListItem( parent, _key, TQCheckListItem::RadioButton ), key( _key )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeEntriesAlternativesEntryType::MergeEntriesAlternativesEntryType( const TQString & _typeString, MergeEntriesAlternativesController *parent )
|
|
: TQCheckListItem( parent, _typeString, TQCheckListItem::RadioButton ), typeString( _typeString ), type( BibTeX::Entry::entryTypeFromString( _typeString ) )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeEntriesAlternativesEntryType::MergeEntriesAlternativesEntryType( BibTeX::Entry::EntryType _type, MergeEntriesAlternativesController *parent )
|
|
: TQCheckListItem( parent, BibTeX::Entry::entryTypeToString( _type ), TQCheckListItem::RadioButton ), typeString( BibTeX::Entry::entryTypeToString( _type ) ), type( _type )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergePreambleAlternativesController::MergePreambleAlternativesController( TQListView *parent )
|
|
: TQCheckListItem( parent, i18n( "Preamble text" ), TQCheckListItem::RadioButtonController )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergePreambleAlternatives::MergePreambleAlternatives( const TQString &_text, MergePreambleAlternativesController *parent )
|
|
:TQCheckListItem( parent, _text, TQCheckListItem::RadioButton ), text( _text )
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
MergeElements::MergeElements( TQWidget *parent )
|
|
: KDialogBase( parent, "MergeElements", true, "undefined", Ok | Cancel | User1 | User2, User1, true, KGuiItem( i18n( "Next" ), "go-next" ), KGuiItem( i18n( "Previous" ), "go-previous" ) ), m_currentCliqueIndex( 0 )
|
|
{
|
|
setupGUI();
|
|
}
|
|
|
|
MergeElements::~MergeElements()
|
|
{
|
|
TDEConfig * config = kapp->config();
|
|
config->setGroup( "MergeElements" );
|
|
saveWindowSize( config );
|
|
}
|
|
|
|
void MergeElements::setupGUI()
|
|
{
|
|
TQWidget *vboxContainer = new TQWidget( this );
|
|
setMainWidget( vboxContainer );
|
|
TQBoxLayout *vboxLayout = new TQVBoxLayout( vboxContainer, 0, KDialog::spacingHint() );
|
|
vboxLayout->setResizeMode( TQLayout::Minimum );
|
|
|
|
TQLabel *label = new TQLabel( i18n( "Select elements to merge. At least two elements must be checked to perform a merge operation. Checked entries will be replaced by the merged element, unchecked elements will be kept." ), vboxContainer );
|
|
label->setAlignment( TQt::WordBreak );
|
|
vboxLayout->addWidget( label );
|
|
m_listViewClique = new TDEListView( vboxContainer );
|
|
m_listViewClique->addColumn( i18n( "Entry/Macro Id" ) );
|
|
m_listViewClique->setFullWidth( true );
|
|
m_listViewClique->setAllColumnsShowFocus( true );
|
|
vboxLayout->addWidget( m_listViewClique );
|
|
vboxLayout->setStretchFactor( m_listViewClique, 1 );
|
|
label->setBuddy( m_listViewClique );
|
|
|
|
m_progressBar = new TQProgressBar( vboxContainer );
|
|
vboxLayout->addWidget( m_progressBar );
|
|
|
|
vboxLayout->addSpacing( KDialog::spacingHint() * 2 );
|
|
|
|
label = new TQLabel( i18n( "Choose from this list which alternatives you want to keep in the merged element." ), vboxContainer );
|
|
label->setAlignment( TQt::WordBreak );
|
|
vboxLayout->addWidget( label );
|
|
m_listViewAlternatives = new TDEListView( vboxContainer );
|
|
m_listViewAlternatives->addColumn( i18n( "Field/Key" ) );
|
|
m_listViewAlternatives->setFullWidth( true );
|
|
m_listViewAlternatives->setAllColumnsShowFocus( true );
|
|
vboxLayout->addWidget( m_listViewAlternatives );
|
|
vboxLayout->setStretchFactor( m_listViewAlternatives, 3 );
|
|
label->setBuddy( m_listViewAlternatives );
|
|
|
|
connect( m_listViewClique, SIGNAL( doubleClicked( TQListViewItem * ) ), this, SLOT( slotPreviewElement( TQListViewItem * ) ) );
|
|
connect( this, SIGNAL( user1Clicked() ), this, SLOT( slotNextClique() ) );
|
|
connect( this, SIGNAL( user2Clicked() ), this, SLOT( slotPreviousClique() ) );
|
|
connect( this, SIGNAL( okClicked() ), this, SLOT( saveCurrentMergeSet() ) );
|
|
}
|
|
|
|
void MergeElements::setClique( int cliqueIndex )
|
|
{
|
|
if ( m_currentCliqueIndex != cliqueIndex )
|
|
saveCurrentMergeSet();
|
|
m_currentCliqueIndex = cliqueIndex;
|
|
|
|
m_listViewClique->clear();
|
|
FindDuplicates::DuplicateClique clique = m_duplicateCliqueList[cliqueIndex];
|
|
|
|
for ( FindDuplicates::DuplicateClique::Iterator it = clique.begin(); it != clique.end(); ++it )
|
|
{
|
|
BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
|
|
if ( entry != NULL )
|
|
{
|
|
MergeElementsCliqueItem *item = new MergeElementsCliqueItem( entry, NULL, NULL, m_listViewClique );
|
|
connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
|
|
}
|
|
else
|
|
{
|
|
BibTeX::Macro *macro = dynamic_cast<BibTeX::Macro*>( *it );
|
|
if ( macro != NULL )
|
|
{
|
|
MergeElementsCliqueItem *item = new MergeElementsCliqueItem( NULL, macro, NULL, m_listViewClique );
|
|
connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
|
|
}
|
|
else
|
|
{
|
|
BibTeX::Preamble *preamble = dynamic_cast<BibTeX::Preamble*>( *it );
|
|
if ( preamble!=NULL )
|
|
{
|
|
MergeElementsCliqueItem *item = new MergeElementsCliqueItem( NULL, NULL, preamble, m_listViewClique );
|
|
connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
restoreCurrentMergeSet();
|
|
|
|
enableButton( User1, ( cliqueIndex < ( int )( m_duplicateCliqueList.size() ) - 1 ) && m_duplicateCliqueList.size() > 1 );
|
|
enableButton( User2, cliqueIndex > 0 && m_duplicateCliqueList.size() > 1 );
|
|
m_progressBar->setProgress( cliqueIndex, m_duplicateCliqueList.size() - 1 );
|
|
}
|
|
|
|
void MergeElements::saveCurrentMergeSet()
|
|
{
|
|
if ( m_mergeSetList[m_currentCliqueIndex] == NULL )
|
|
m_mergeSetList[m_currentCliqueIndex] = new MergeSet;
|
|
else
|
|
{
|
|
m_mergeSetList[m_currentCliqueIndex]->entries.clear();
|
|
m_mergeSetList[m_currentCliqueIndex]->fields.clear();
|
|
}
|
|
m_mergeSetList[m_currentCliqueIndex]->type = BibTeX::Entry::etUnknown;
|
|
m_mergeSetList[m_currentCliqueIndex]->typeString = TQString::null;
|
|
m_mergeSetList[m_currentCliqueIndex]->id = TQString::null;
|
|
m_mergeSetList[m_currentCliqueIndex]->macroKey = TQString::null;
|
|
m_mergeSetList[m_currentCliqueIndex]->macroValue = NULL;
|
|
m_mergeSetList[m_currentCliqueIndex]->preambleText=TQString::null;
|
|
|
|
for ( TQListViewItemIterator it( m_listViewClique, TQListViewItemIterator::Checked ); it.current(); ++it )
|
|
{
|
|
MergeElementsCliqueItem *eci = dynamic_cast<MergeElementsCliqueItem*>( *it );
|
|
BibTeX::Entry *entry = eci->entry;
|
|
if ( entry != NULL )
|
|
m_mergeSetList[m_currentCliqueIndex]->entries.append( entry );
|
|
BibTeX::Macro *macro = eci->macro;
|
|
if ( macro != NULL )
|
|
m_mergeSetList[m_currentCliqueIndex]->macros.append( macro );
|
|
BibTeX::Preamble *preamble = eci->preamble;
|
|
if ( preamble !=NULL )
|
|
m_mergeSetList[m_currentCliqueIndex]->preambles.append( preamble );
|
|
}
|
|
|
|
for ( TQListViewItemIterator it( m_listViewAlternatives, TQListViewItemIterator::Checked ); it.current(); ++it )
|
|
{
|
|
MergeEntriesAlternativesItem *item = dynamic_cast<MergeEntriesAlternativesItem*>( *it );
|
|
if ( item != NULL )
|
|
{
|
|
BibTeX::EntryField *field = item->field;
|
|
m_mergeSetList[m_currentCliqueIndex]->fields.append( field );
|
|
}
|
|
else
|
|
{
|
|
MergeElementsAlternativesId *item = dynamic_cast<MergeElementsAlternativesId*>( *it );
|
|
if ( item != NULL )
|
|
m_mergeSetList[m_currentCliqueIndex]->id = item->id;
|
|
else
|
|
{
|
|
MergeEntriesAlternativesEntryType *itemT = dynamic_cast<MergeEntriesAlternativesEntryType*>( *it );
|
|
if ( itemT != NULL )
|
|
{
|
|
m_mergeSetList[m_currentCliqueIndex]->typeString = itemT->typeString;
|
|
m_mergeSetList[m_currentCliqueIndex]->type = itemT->type;
|
|
}
|
|
else
|
|
{
|
|
MergeMacroAlternativesKey *itemK = dynamic_cast<MergeMacroAlternativesKey*>( *it );
|
|
if ( itemK != NULL )
|
|
m_mergeSetList[m_currentCliqueIndex]->macroKey = itemK->key;
|
|
else
|
|
{
|
|
MergeMacrosAlternativesItem *itemMA = dynamic_cast<MergeMacrosAlternativesItem*>( *it );
|
|
if ( itemMA != NULL )
|
|
m_mergeSetList[m_currentCliqueIndex]->macroValue = itemMA->value;
|
|
else
|
|
{
|
|
MergePreambleAlternatives *itemP=dynamic_cast<MergePreambleAlternatives*>( *it );
|
|
if ( itemP!=NULL )
|
|
m_mergeSetList[m_currentCliqueIndex]->preambleText=itemP->text;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MergeElements::restoreCurrentMergeSet()
|
|
{
|
|
if ( m_mergeSetList[m_currentCliqueIndex] == NULL )
|
|
{
|
|
m_listViewAlternatives->clear();
|
|
return;
|
|
}
|
|
|
|
for ( TQListViewItemIterator it( m_listViewClique ); it.current(); ++it )
|
|
{
|
|
MergeElementsCliqueItem *item = dynamic_cast<MergeElementsCliqueItem*>( *it );
|
|
BibTeX::Entry *entry = item->entry;
|
|
BibTeX::Macro *macro = item->macro;
|
|
BibTeX::Preamble *preamble = item->preamble;
|
|
if ( entry != NULL )
|
|
for ( TQValueList<BibTeX::Entry*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->entries.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->entries.end(); ++it2 )
|
|
{
|
|
if ( entry->id() == ( *it2 )->id() )
|
|
{
|
|
item->setOn( true );
|
|
break;
|
|
}
|
|
}
|
|
else if ( macro != NULL )
|
|
{
|
|
for ( TQValueList<BibTeX::Macro*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->macros.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->macros.end(); ++it2 )
|
|
if ( macro->key() == ( *it2 )->key() )
|
|
{
|
|
item->setOn( true );
|
|
break;
|
|
}
|
|
}
|
|
else if ( preamble!=NULL )
|
|
for ( TQValueList<BibTeX::Preamble*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->preambles.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->preambles.end(); ++it2 )
|
|
if ( preamble->value()->text() == ( *it2 )->value()->text() )
|
|
{
|
|
item->setOn( true );
|
|
break;
|
|
}
|
|
}
|
|
|
|
slotRefreshAlternatives();
|
|
|
|
for ( TQListViewItemIterator it( m_listViewAlternatives ); it.current(); ++it )
|
|
{
|
|
MergeEntriesAlternativesItem *item = dynamic_cast<MergeEntriesAlternativesItem*>( *it );
|
|
if ( item != NULL )
|
|
{
|
|
for ( TQValueList<BibTeX::EntryField*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->fields.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->fields.end(); ++it2 )
|
|
if ( item->field->fieldTypeName().lower() == ( *it2 )->fieldTypeName().lower() && item->field->value()->text() == ( *it2 )->value()->text() )
|
|
{
|
|
item->setOn( true );
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MergeElementsAlternativesId *item = dynamic_cast<MergeElementsAlternativesId*>( *it );
|
|
if ( item != NULL )
|
|
{
|
|
if ( item->id == m_mergeSetList[m_currentCliqueIndex]->id )
|
|
item->setOn( true );
|
|
}
|
|
else
|
|
{
|
|
MergeEntriesAlternativesEntryType *item = dynamic_cast<MergeEntriesAlternativesEntryType*>( *it );
|
|
if ( item != NULL )
|
|
{
|
|
if (( item->type != BibTeX::Entry::etUnknown && item->type == m_mergeSetList[m_currentCliqueIndex]->type ) || ( item->typeString.lower() == m_mergeSetList[m_currentCliqueIndex]->typeString.lower() ) )
|
|
item->setOn( true );
|
|
}
|
|
else
|
|
{
|
|
MergeMacrosAlternativesItem *mai = dynamic_cast<MergeMacrosAlternativesItem*>( *it );
|
|
if ( mai != NULL )
|
|
{
|
|
if ( mai->value == m_mergeSetList[m_currentCliqueIndex]->macroValue )
|
|
mai->setOn( true );
|
|
}
|
|
else
|
|
{
|
|
MergeMacroAlternativesKey *mak = dynamic_cast<MergeMacroAlternativesKey*>( *it );
|
|
if ( mak != NULL )
|
|
{
|
|
if ( mak->key == m_mergeSetList[m_currentCliqueIndex]->macroKey )
|
|
mak->setOn( true );
|
|
}
|
|
else
|
|
{
|
|
MergePreambleAlternatives *mpa =dynamic_cast<MergePreambleAlternatives*>( *it );
|
|
if ( mpa!=NULL )
|
|
{
|
|
if ( mpa->text==m_mergeSetList[m_currentCliqueIndex]->preambleText )
|
|
mpa->setOn( true );
|
|
}
|
|
else
|
|
tqDebug( "Item is of unknown type" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MergeElements::applyMergeSet( BibTeX::File *bibTeXFile, BibTeX::File *otherBibTeXFile )
|
|
{
|
|
int n = m_duplicateCliqueList.size();
|
|
for ( int i = 0; i < n; ++i )
|
|
{
|
|
if ( m_mergeSetList[i] == NULL ) continue;
|
|
|
|
if ( !m_mergeSetList[i]->entries.isEmpty() )
|
|
{
|
|
TQString id = m_mergeSetList[i]->id == TQString::null ? ( *m_mergeSetList[i]->entries.begin() )->id() : m_mergeSetList[i]->id;
|
|
|
|
BibTeX::Entry *newEntry = NULL;
|
|
if ( m_mergeSetList[i]->type == BibTeX::Entry::etUnknown )
|
|
{
|
|
if ( m_mergeSetList[i]->typeString == TQString::null )
|
|
{
|
|
BibTeX::Entry *firstEntry = *m_mergeSetList[i]->entries.begin();
|
|
if ( firstEntry->entryType() == BibTeX::Entry::etUnknown )
|
|
newEntry = new BibTeX::Entry( firstEntry->entryTypeString(), id );
|
|
else
|
|
newEntry = new BibTeX::Entry( firstEntry->entryType(), id );
|
|
}
|
|
else
|
|
newEntry = new BibTeX::Entry( m_mergeSetList[i]->typeString, id );
|
|
}
|
|
else
|
|
newEntry = new BibTeX::Entry( m_mergeSetList[i]->type, id );
|
|
|
|
for ( TQValueList<BibTeX::EntryField*>::Iterator it = m_mergeSetList[i]->fields.begin(); it != m_mergeSetList[i]->fields.end(); ++it )
|
|
{
|
|
newEntry->addField( new BibTeX::EntryField( *it ) );
|
|
}
|
|
|
|
for ( TQValueList<BibTeX::Entry*>::Iterator it = m_mergeSetList[i]->entries.begin(); it != m_mergeSetList[i]->entries.end(); ++it )
|
|
for ( TQValueList<BibTeX::EntryField*>::ConstIterator fIt = ( *it )->begin(); fIt != ( *it )->end(); ++fIt )
|
|
if ( newEntry->getField(( *fIt )->fieldTypeName() ) == NULL )
|
|
{
|
|
newEntry->addField( new BibTeX::EntryField( *fIt ) );
|
|
}
|
|
|
|
for ( TQValueList<BibTeX::Entry*>::Iterator it = m_mergeSetList[i]->entries.begin(); it != m_mergeSetList[i]->entries.end(); ++it )
|
|
{
|
|
BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( bibTeXFile->containsKey(( *it )->id() ) );
|
|
if ( entry != NULL )
|
|
bibTeXFile->deleteElement( entry );
|
|
else
|
|
{
|
|
BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( otherBibTeXFile->containsKey(( *it )->id() ) );
|
|
if ( entry != NULL )
|
|
otherBibTeXFile->deleteElement( entry );
|
|
}
|
|
}
|
|
bibTeXFile->appendElement( newEntry );
|
|
}
|
|
else if ( !m_mergeSetList[i]->macros.isEmpty() )
|
|
{
|
|
BibTeX::Macro *newMacro = new BibTeX::Macro( m_mergeSetList[i]->macroKey );
|
|
newMacro->setValue( m_mergeSetList[i]->macroValue );
|
|
|
|
for ( TQValueList<BibTeX::Macro*>::Iterator it = m_mergeSetList[i]->macros.begin(); it != m_mergeSetList[i]->macros.end(); ++it )
|
|
{
|
|
bibTeXFile->deleteElement( *it );
|
|
if ( otherBibTeXFile != NULL )
|
|
otherBibTeXFile->deleteElement( *it );
|
|
}
|
|
|
|
bibTeXFile->appendElement( newMacro );
|
|
}
|
|
else if ( !m_mergeSetList[i]->preambles.isEmpty() )
|
|
{
|
|
BibTeX::Preamble *newPreamble = new BibTeX::Preamble( m_mergeSetList[i]->preambleText );
|
|
|
|
for ( TQValueList<BibTeX::Preamble*>::Iterator it = m_mergeSetList[i]->preambles.begin(); it != m_mergeSetList[i]->preambles.end(); ++it )
|
|
{
|
|
bibTeXFile->deleteElement( *it );
|
|
if ( otherBibTeXFile != NULL )
|
|
otherBibTeXFile->deleteElement( *it );
|
|
}
|
|
|
|
bibTeXFile->appendElement( newPreamble );
|
|
}
|
|
}
|
|
}
|
|
|
|
int MergeElements::mergeDuplicates( BibTeX::File *bibTeXFile )
|
|
{
|
|
setCaption( i18n( "Find Duplicates" ) );
|
|
Settings * settings = Settings::self( NULL );
|
|
int sensitivity = ( int )( FindDuplicates::maxDistance / exp( log( 10 ) * settings->editing_findDuplicatesSensitivity / 10.0 ) );
|
|
tqDebug( "sensitivity= %i / %i", sensitivity, FindDuplicates::maxDistance );
|
|
FindDuplicates findDuplicates( m_duplicateCliqueList, sensitivity, bibTeXFile, parentWidget( true ) );
|
|
|
|
if ( m_duplicateCliqueList.isEmpty() )
|
|
{
|
|
KMessageBox::information( parentWidget( true ), i18n( "No duplicates found." ), i18n( "Find Duplicates" ) );
|
|
return TQDialog::Rejected;
|
|
}
|
|
|
|
m_mergeSetList = new MergeSet*[m_duplicateCliqueList.size()];
|
|
memset( m_mergeSetList, 0, sizeof( MergeSet* )*m_duplicateCliqueList.size() );
|
|
|
|
tqDebug( "%i cliques", m_duplicateCliqueList.size() );
|
|
setClique( 0 );
|
|
|
|
int result = exec();
|
|
if ( result == TQDialog::Accepted )
|
|
applyMergeSet( bibTeXFile );
|
|
|
|
delete[] m_mergeSetList;
|
|
|
|
return result;
|
|
}
|
|
|
|
void MergeElements::slotRefreshAlternatives()
|
|
{
|
|
TQMap<BibTeX::EntryField::FieldType, MergeEntriesAlternativesController*> mapFieldToController;
|
|
TQMap<BibTeX::EntryField::FieldType, First> firstEntryData;
|
|
bool first = true;
|
|
MergePreambleAlternativesController* preambleController = NULL;
|
|
MergeMacrosAlternativesController* macroKeyController = NULL;
|
|
MergeMacrosAlternativesController* macroValueController = NULL;
|
|
MergeEntriesAlternativesController *idController = NULL;
|
|
MergeEntriesAlternativesController *typeController = NULL;
|
|
TQString firstId = TQString::null;
|
|
TQString firstMacroKey = TQString::null;
|
|
BibTeX::Value *firstMacroValue = NULL;
|
|
TQString firstPreambleText = TQString::null;
|
|
BibTeX::Entry::EntryType firstType = BibTeX::Entry::etUnknown;
|
|
TQString firstTypeString = TQString::null;
|
|
|
|
m_listViewAlternatives->clear();
|
|
|
|
for ( TQListViewItemIterator it( m_listViewClique, TQListViewItemIterator::Checked ); it.current(); ++it )
|
|
{
|
|
MergeElementsCliqueItem *meci = dynamic_cast<MergeElementsCliqueItem*>( *it );
|
|
BibTeX::Entry *entry = NULL;
|
|
BibTeX::Macro *macro = NULL;
|
|
BibTeX::Preamble *preamble = NULL;
|
|
if ( meci != NULL && ( entry = meci->entry ) != NULL )
|
|
{
|
|
if ( first )
|
|
{
|
|
firstId = entry->id();
|
|
firstType = entry->entryType();
|
|
firstTypeString = entry->entryTypeString();
|
|
for ( BibTeX::Entry::EntryFields::const_iterator efi = entry->begin(); efi != entry->end(); ++efi )
|
|
{
|
|
First first;
|
|
first.entry = entry;
|
|
first.field = *efi;
|
|
firstEntryData.insert(( *efi )->fieldType(), first );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( idController == NULL )
|
|
{
|
|
if ( entry->id() != firstId )
|
|
{
|
|
idController = new MergeEntriesAlternativesController( i18n( "Id" ), m_listViewAlternatives );
|
|
idController->setOpen( true );
|
|
MergeElementsAlternativesId *item = new MergeElementsAlternativesId( firstId, idController );
|
|
item->setOn( true );
|
|
new MergeElementsAlternativesId( entry->id(), idController );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TQString thisText = entry->id();
|
|
bool isNew = true;
|
|
for ( TQListViewItem *cur = idController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
|
|
{
|
|
MergeElementsAlternativesId *meai = dynamic_cast<MergeElementsAlternativesId*>( cur );
|
|
isNew = meai->id != thisText;
|
|
}
|
|
if ( isNew )
|
|
new MergeElementsAlternativesId( thisText, idController );
|
|
}
|
|
|
|
if ( typeController == NULL )
|
|
{
|
|
if (( firstType != BibTeX::Entry::etUnknown && entry->entryType() != firstType ) || ( entry->entryTypeString().lower() != entry->entryTypeString().lower() ) )
|
|
{
|
|
typeController = new MergeEntriesAlternativesController( i18n( "Type" ), m_listViewAlternatives );
|
|
typeController->setOpen( true );
|
|
MergeEntriesAlternativesEntryType *item = firstType != BibTeX::Entry::etUnknown ? new MergeEntriesAlternativesEntryType( firstType, typeController ) : new MergeEntriesAlternativesEntryType( firstTypeString, typeController );
|
|
item->setOn( true );
|
|
if ( entry->entryType() != BibTeX::Entry::etUnknown )
|
|
new MergeEntriesAlternativesEntryType( entry->entryType(), typeController );
|
|
else
|
|
new MergeEntriesAlternativesEntryType( entry->entryTypeString(), typeController );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TQString typeString = entry->entryTypeString();
|
|
BibTeX::Entry::EntryType type = entry->entryType();
|
|
bool isNew = true;
|
|
for ( TQListViewItem *cur = typeController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
|
|
{
|
|
MergeEntriesAlternativesEntryType *meat = dynamic_cast<MergeEntriesAlternativesEntryType*>( cur );
|
|
isNew = type == BibTeX::Entry::etUnknown && meat->typeString != typeString || meat->type != type;
|
|
}
|
|
if ( isNew )
|
|
{
|
|
if ( type != BibTeX::Entry::etUnknown )
|
|
new MergeEntriesAlternativesEntryType( type, typeController );
|
|
else
|
|
new MergeEntriesAlternativesEntryType( typeString, typeController );
|
|
}
|
|
}
|
|
|
|
for ( BibTeX::Entry::EntryFields::const_iterator efi = entry->begin(); efi != entry->end(); ++efi )
|
|
if ( mapFieldToController.contains(( *efi )->fieldType() ) )
|
|
{
|
|
MergeEntriesAlternativesController *controller = mapFieldToController[( *efi )->fieldType()];
|
|
TQString thisText = ( *efi )->value()->text();
|
|
bool isNew = true;
|
|
for ( TQListViewItem *cur = controller->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
|
|
{
|
|
MergeEntriesAlternativesItem *meai = dynamic_cast<MergeEntriesAlternativesItem*>( cur );
|
|
isNew = meai->field->value()->text() != thisText;
|
|
}
|
|
if ( isNew )
|
|
new MergeEntriesAlternativesItem( *efi, controller );
|
|
}
|
|
else if ( firstEntryData.contains(( *efi )->fieldType() ) )
|
|
{
|
|
TQString firstText = firstEntryData[( *efi )->fieldType()].field->value()->text();
|
|
TQString thisText = ( *efi )->value()->text();
|
|
if ( firstText != thisText )
|
|
{
|
|
MergeEntriesAlternativesController *controller = new MergeEntriesAlternativesController(( *efi )->fieldType(), m_listViewAlternatives );
|
|
controller->setOpen( true );
|
|
MergeEntriesAlternativesItem *item = new MergeEntriesAlternativesItem( firstEntryData[( *efi )->fieldType()].field, controller );
|
|
item->setOn( true );
|
|
item = new MergeEntriesAlternativesItem( *efi, controller );
|
|
mapFieldToController.insert(( *efi )->fieldType(), controller );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
First first;
|
|
first.entry = entry;
|
|
first.field = *efi;
|
|
firstEntryData.insert(( *efi )->fieldType(), first );
|
|
}
|
|
}
|
|
}
|
|
else if ( meci != NULL && ( macro = meci->macro ) != NULL )
|
|
{
|
|
if ( first )
|
|
{
|
|
firstMacroKey = macro->key();
|
|
firstMacroValue = macro->value();
|
|
}
|
|
else
|
|
{
|
|
if ( macroKeyController == NULL )
|
|
{
|
|
if ( macro->key() != firstMacroKey )
|
|
{
|
|
macroKeyController = new MergeMacrosAlternativesController( true, m_listViewAlternatives );
|
|
macroKeyController->setOpen( true );
|
|
MergeMacroAlternativesKey *item = new MergeMacroAlternativesKey( firstMacroKey, macroKeyController );
|
|
item->setOn( true );
|
|
new MergeMacroAlternativesKey( macro->key(), macroKeyController );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TQString thisText = macro->key();
|
|
bool isNew = true;
|
|
for ( TQListViewItem *cur = macroKeyController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
|
|
{
|
|
MergeMacroAlternativesKey *mak = dynamic_cast<MergeMacroAlternativesKey*>( cur );
|
|
isNew = mak->key != thisText;
|
|
}
|
|
if ( isNew )
|
|
new MergeMacroAlternativesKey( thisText, macroKeyController );
|
|
}
|
|
}
|
|
|
|
if ( macroValueController == NULL )
|
|
{
|
|
if ( firstMacroValue->text() != macro->value()->text() )
|
|
{
|
|
macroValueController = new MergeMacrosAlternativesController( false, m_listViewAlternatives );
|
|
macroValueController->setOpen( true );
|
|
MergeMacrosAlternativesItem *item = new MergeMacrosAlternativesItem( firstMacroValue, macroValueController );
|
|
item->setOn( true );
|
|
new MergeMacrosAlternativesItem( macro->value(), macroValueController );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TQString macroString = macro->value()->text();
|
|
bool isNew = true;
|
|
for ( TQListViewItem *cur = macroValueController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
|
|
{
|
|
MergeMacrosAlternativesItem *mai = dynamic_cast<MergeMacrosAlternativesItem*>( cur );
|
|
isNew = macroString != mai->value->text();
|
|
}
|
|
if ( isNew )
|
|
new MergeMacrosAlternativesItem( macro->value(), macroValueController );
|
|
}
|
|
}
|
|
else if ( meci != NULL && ( preamble = meci->preamble ) != NULL )
|
|
{
|
|
if ( first )
|
|
firstPreambleText = preamble->value()->text();
|
|
else
|
|
{
|
|
if ( preambleController == NULL )
|
|
{
|
|
if ( preamble->value()->text() != firstPreambleText )
|
|
{
|
|
preambleController = new MergePreambleAlternativesController( m_listViewAlternatives );
|
|
preambleController->setOpen( true );
|
|
MergePreambleAlternatives *item = new MergePreambleAlternatives( firstPreambleText, preambleController );
|
|
item->setOn( true );
|
|
new MergePreambleAlternatives( preamble->value()->text(), preambleController );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TQString thisText = preamble->value()->text();
|
|
bool isNew = true;
|
|
for ( TQListViewItem *cur = preambleController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
|
|
{
|
|
MergePreambleAlternatives *mpa = dynamic_cast<MergePreambleAlternatives*>( cur );
|
|
isNew = mpa->text != thisText;
|
|
}
|
|
if ( isNew )
|
|
new MergePreambleAlternatives( thisText, preambleController );
|
|
}
|
|
}
|
|
}
|
|
first = false;
|
|
}
|
|
}
|
|
|
|
void MergeElements::slotNextClique()
|
|
{
|
|
if ( m_currentCliqueIndex < ( int )( m_duplicateCliqueList.size() ) - 1 )
|
|
{
|
|
setClique( m_currentCliqueIndex + 1 );
|
|
}
|
|
else
|
|
enableButton( User1, false );
|
|
}
|
|
|
|
void MergeElements::slotPreviousClique()
|
|
{
|
|
if ( m_currentCliqueIndex > 0 )
|
|
{
|
|
setClique( m_currentCliqueIndex - 1 );
|
|
}
|
|
else
|
|
enableButton( User2, false );
|
|
}
|
|
|
|
void MergeElements::slotPreviewElement( TQListViewItem *item )
|
|
{
|
|
MergeElementsCliqueItem *meci = dynamic_cast<MergeElementsCliqueItem*>( item );
|
|
if ( meci != NULL && meci->entry != NULL )
|
|
KBibTeX::EntryWidget::execute( meci->entry, NULL, TRUE, FALSE, this );
|
|
else if ( meci != NULL && meci->macro != NULL )
|
|
KBibTeX::MacroWidget::execute( meci->macro, TRUE, this );
|
|
else if ( meci!=NULL&& meci->preamble!=NULL )
|
|
KBibTeX::PreambleWidget::execute( meci->preamble, TRUE, this );
|
|
}
|
|
|
|
/* This function was taken form TDEMainWindow of KDE 3.5 and modified to fit KBibTeX */
|
|
void MergeElements::saveWindowSize( TDEConfig *config ) const
|
|
{
|
|
int scnum = TQApplication::desktop()->screenNumber( parentWidget() );
|
|
TQRect desk = TQApplication::desktop()->screenGeometry( scnum );
|
|
int w, h;
|
|
#if defined Q_WS_X11
|
|
// save maximalization as desktop size + 1 in that direction
|
|
KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState );
|
|
w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
|
|
h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
|
|
#else
|
|
if ( isMaximized() )
|
|
{
|
|
w = desk.width() + 1;
|
|
h = desk.height() + 1;
|
|
}
|
|
//TODO: add "Maximized" property instead "+1" hack
|
|
#endif
|
|
TQRect size( desk.width(), w, desk.height(), h );
|
|
bool defaultSize = false;//( size == d->defaultWindowSize );
|
|
TQString widthString = TQString::fromLatin1( "Width %1" ).arg( desk.width() );
|
|
TQString heightString = TQString::fromLatin1( "Height %1" ).arg( desk.height() );
|
|
if ( !config->hasDefault( widthString ) && defaultSize )
|
|
config->revertToDefault( widthString );
|
|
else
|
|
config->writeEntry( widthString, w );
|
|
|
|
if ( !config->hasDefault( heightString ) && defaultSize )
|
|
config->revertToDefault( heightString );
|
|
else
|
|
config->writeEntry( heightString, h );
|
|
}
|
|
|
|
void MergeElements::showEvent( TQShowEvent * )
|
|
{
|
|
tqDebug( "showEvent" );
|
|
TQTimer::singleShot( 10, this, SLOT( slotRestore() ) );
|
|
}
|
|
|
|
void MergeElements::slotRestore()
|
|
{
|
|
tqDebug( "slotRestore" );
|
|
TDEConfig * config = kapp->config();
|
|
config->setGroup( "MergeElements" );
|
|
restoreWindowSize( config );
|
|
}
|
|
|
|
/* This function was taken form TDEMainWindow of KDE 3.5 and modified to fit KBibTeX */
|
|
void MergeElements::restoreWindowSize( TDEConfig *config )
|
|
{
|
|
// restore the size
|
|
int scnum = TQApplication::desktop()->screenNumber( parentWidget() );
|
|
TQRect desk = TQApplication::desktop()->screenGeometry( scnum );
|
|
TQSize size( config->readNumEntry( TQString::fromLatin1( "Width %1" ).arg( desk.width() ), 0 ),
|
|
config->readNumEntry( TQString::fromLatin1( "Height %1" ).arg( desk.height() ), 0 ) );
|
|
if ( size.isEmpty() )
|
|
{
|
|
// try the KDE 2.0 way
|
|
size = TQSize( config->readNumEntry( TQString::fromLatin1( "Width" ), 0 ),
|
|
config->readNumEntry( TQString::fromLatin1( "Height" ), 0 ) );
|
|
if ( !size.isEmpty() )
|
|
{
|
|
// make sure the other resolutions don't get old settings
|
|
config->writeEntry( TQString::fromLatin1( "Width" ), 0 );
|
|
config->writeEntry( TQString::fromLatin1( "Height" ), 0 );
|
|
}
|
|
}
|
|
if ( !size.isEmpty() )
|
|
{
|
|
#ifdef Q_WS_X11
|
|
int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
|
|
| ( size.height() > desk.height() ? NET::MaxVert : 0 );
|
|
if (( state & NET::Max ) == NET::Max )
|
|
; // no resize
|
|
else if (( state & NET::MaxHoriz ) == NET::MaxHoriz )
|
|
resize( width(), size.height() );
|
|
else if (( state & NET::MaxVert ) == NET::MaxVert )
|
|
resize( size.width(), height() );
|
|
else
|
|
resize( size );
|
|
// TQWidget::showMaximized() is both insufficient and broken
|
|
KWin::setState( winId(), state );
|
|
#else
|
|
if ( size.width() > desk.width() || size.height() > desk.height() )
|
|
setWindowState( WindowMaximized );
|
|
else
|
|
resize( size );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|
|
#include "mergeelements.moc"
|