From 998f21e02a725cd553d7c278819f67cd81295af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sl=C3=A1vek=20Banko?= Date: Mon, 24 Jun 2013 02:08:15 +0200 Subject: Initial import --- src/mergeelements.cpp | 864 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 864 insertions(+) create mode 100644 src/mergeelements.cpp (limited to 'src/mergeelements.cpp') diff --git a/src/mergeelements.cpp b/src/mergeelements.cpp new file mode 100644 index 0000000..9ad05d7 --- /dev/null +++ b/src/mergeelements.cpp @@ -0,0 +1,864 @@ +/*************************************************************************** + * 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 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mergeelements.h" + +namespace KBibTeX +{ + MergeElementsCliqueItem::MergeElementsCliqueItem( BibTeX::Entry* _entry, BibTeX::Macro* _macro, BibTeX::Preamble* _preamble, QListView *parent ) + : QCheckListItem( parent, _entry == NULL ?( _macro == NULL ? _preamble->value()->text() : _macro->key() ) : _entry->id(), QCheckListItem::CheckBox ), entry( _entry ), macro( _macro ), preamble( _preamble ) + { + // nothing + } + + void MergeElementsCliqueItem::stateChange( bool ) + { + emit stateChanged( this ); + }; + + MergeEntriesAlternativesController::MergeEntriesAlternativesController( const QString &label, QListView *parent ) + : QCheckListItem( parent, label, QCheckListItem::RadioButtonController ), fieldType( BibTeX::EntryField::ftUnknown ), fieldName( label ) + { + // nothing + } + + MergeEntriesAlternativesController::MergeEntriesAlternativesController( BibTeX::EntryField::FieldType _fieldType, QListView *parent ) + : QCheckListItem( parent, BibTeX::EntryField::fieldTypeToString( _fieldType ), QCheckListItem::RadioButtonController ), fieldType( _fieldType ), fieldName( BibTeX::EntryField::fieldTypeToString( _fieldType ) ) + { + // nothing + } + + MergeMacrosAlternativesController::MergeMacrosAlternativesController( bool isKey, QListView *parent ) + : QCheckListItem( parent, isKey ? i18n( "Key" ) : i18n( "Value" ), QCheckListItem::RadioButtonController ) + { + // nothing + } + + MergeEntriesAlternativesItem::MergeEntriesAlternativesItem( BibTeX::EntryField *_field, MergeEntriesAlternativesController *parent ) + : QCheckListItem( parent, _field->value()->text(), QCheckListItem::RadioButton ), field( _field ) + { + // nothing + } + + MergeMacrosAlternativesItem::MergeMacrosAlternativesItem( BibTeX::Value *_value, MergeMacrosAlternativesController *parent ) + : QCheckListItem( parent, _value->text(), QCheckListItem::RadioButton ), value( _value ) + { + // nothing + } + + MergeElementsAlternativesId::MergeElementsAlternativesId( const QString & _id, MergeEntriesAlternativesController *parent ) : QCheckListItem( parent, _id, QCheckListItem::RadioButton ), id( _id ) + { + // nothing + } + + MergeMacroAlternativesKey::MergeMacroAlternativesKey( const QString & _key, MergeMacrosAlternativesController *parent ) : QCheckListItem( parent, _key, QCheckListItem::RadioButton ), key( _key ) + { + // nothing + } + + MergeEntriesAlternativesEntryType::MergeEntriesAlternativesEntryType( const QString & _typeString, MergeEntriesAlternativesController *parent ) + : QCheckListItem( parent, _typeString, QCheckListItem::RadioButton ), typeString( _typeString ), type( BibTeX::Entry::entryTypeFromString( _typeString ) ) + { + // nothing + } + + MergeEntriesAlternativesEntryType::MergeEntriesAlternativesEntryType( BibTeX::Entry::EntryType _type, MergeEntriesAlternativesController *parent ) + : QCheckListItem( parent, BibTeX::Entry::entryTypeToString( _type ), QCheckListItem::RadioButton ), typeString( BibTeX::Entry::entryTypeToString( _type ) ), type( _type ) + { + // nothing + } + + MergePreambleAlternativesController::MergePreambleAlternativesController( QListView *parent ) + : QCheckListItem( parent, i18n( "Preamble text" ), QCheckListItem::RadioButtonController ) + { + // nothing + } + + MergePreambleAlternatives::MergePreambleAlternatives( const QString &_text, MergePreambleAlternativesController *parent ) + :QCheckListItem( parent, _text, QCheckListItem::RadioButton ), text( _text ) + { + // nothing + } + + MergeElements::MergeElements( QWidget *parent ) + : KDialogBase( parent, "MergeElements", true, "undefined", Ok | Cancel | User1 | User2, User1, true, KGuiItem( i18n( "Next" ), "next" ), KGuiItem( i18n( "Previous" ), "previous" ) ), m_currentCliqueIndex( 0 ) + { + setupGUI(); + } + + MergeElements::~MergeElements() + { + KConfig * config = kapp->config(); + config->setGroup( "MergeElements" ); + saveWindowSize( config ); + } + + void MergeElements::setupGUI() + { + QWidget *vboxContainer = new QWidget( this ); + setMainWidget( vboxContainer ); + QBoxLayout *vboxLayout = new QVBoxLayout( vboxContainer, 0, KDialog::spacingHint() ); + vboxLayout->setResizeMode( QLayout::Minimum ); + + QLabel *label = new QLabel( 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( Qt::WordBreak ); + vboxLayout->addWidget( label ); + m_listViewClique = new KListView( 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 QProgressBar( vboxContainer ); + vboxLayout->addWidget( m_progressBar ); + + vboxLayout->addSpacing( KDialog::spacingHint() * 2 ); + + label = new QLabel( i18n( "Choose from this list which alternatives you want to keep in the merged element." ), vboxContainer ); + label->setAlignment( Qt::WordBreak ); + vboxLayout->addWidget( label ); + m_listViewAlternatives = new KListView( 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( QListViewItem * ) ), this, SLOT( slotPreviewElement( QListViewItem * ) ) ); + 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( *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( *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( *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 = QString::null; + m_mergeSetList[m_currentCliqueIndex]->id = QString::null; + m_mergeSetList[m_currentCliqueIndex]->macroKey = QString::null; + m_mergeSetList[m_currentCliqueIndex]->macroValue = NULL; + m_mergeSetList[m_currentCliqueIndex]->preambleText=QString::null; + + for ( QListViewItemIterator it( m_listViewClique, QListViewItemIterator::Checked ); it.current(); ++it ) + { + MergeElementsCliqueItem *eci = dynamic_cast( *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 ( QListViewItemIterator it( m_listViewAlternatives, QListViewItemIterator::Checked ); it.current(); ++it ) + { + MergeEntriesAlternativesItem *item = dynamic_cast( *it ); + if ( item != NULL ) + { + BibTeX::EntryField *field = item->field; + m_mergeSetList[m_currentCliqueIndex]->fields.append( field ); + } + else + { + MergeElementsAlternativesId *item = dynamic_cast( *it ); + if ( item != NULL ) + m_mergeSetList[m_currentCliqueIndex]->id = item->id; + else + { + MergeEntriesAlternativesEntryType *itemT = dynamic_cast( *it ); + if ( itemT != NULL ) + { + m_mergeSetList[m_currentCliqueIndex]->typeString = itemT->typeString; + m_mergeSetList[m_currentCliqueIndex]->type = itemT->type; + } + else + { + MergeMacroAlternativesKey *itemK = dynamic_cast( *it ); + if ( itemK != NULL ) + m_mergeSetList[m_currentCliqueIndex]->macroKey = itemK->key; + else + { + MergeMacrosAlternativesItem *itemMA = dynamic_cast( *it ); + if ( itemMA != NULL ) + m_mergeSetList[m_currentCliqueIndex]->macroValue = itemMA->value; + else + { + MergePreambleAlternatives *itemP=dynamic_cast( *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 ( QListViewItemIterator it( m_listViewClique ); it.current(); ++it ) + { + MergeElementsCliqueItem *item = dynamic_cast( *it ); + BibTeX::Entry *entry = item->entry; + BibTeX::Macro *macro = item->macro; + BibTeX::Preamble *preamble = item->preamble; + if ( entry != NULL ) + for ( QValueList::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 ( QValueList::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 ( QValueList::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 ( QListViewItemIterator it( m_listViewAlternatives ); it.current(); ++it ) + { + MergeEntriesAlternativesItem *item = dynamic_cast( *it ); + if ( item != NULL ) + { + for ( QValueList::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( *it ); + if ( item != NULL ) + { + if ( item->id == m_mergeSetList[m_currentCliqueIndex]->id ) + item->setOn( true ); + } + else + { + MergeEntriesAlternativesEntryType *item = dynamic_cast( *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( *it ); + if ( mai != NULL ) + { + if ( mai->value == m_mergeSetList[m_currentCliqueIndex]->macroValue ) + mai->setOn( true ); + } + else + { + MergeMacroAlternativesKey *mak = dynamic_cast( *it ); + if ( mak != NULL ) + { + if ( mak->key == m_mergeSetList[m_currentCliqueIndex]->macroKey ) + mak->setOn( true ); + } + else + { + MergePreambleAlternatives *mpa =dynamic_cast( *it ); + if ( mpa!=NULL ) + { + if ( mpa->text==m_mergeSetList[m_currentCliqueIndex]->preambleText ) + mpa->setOn( true ); + } + else + qDebug( "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() ) + { + QString id = m_mergeSetList[i]->id == QString::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 == QString::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 ( QValueList::Iterator it = m_mergeSetList[i]->fields.begin(); it != m_mergeSetList[i]->fields.end(); ++it ) + { + newEntry->addField( new BibTeX::EntryField( *it ) ); + } + + for ( QValueList::Iterator it = m_mergeSetList[i]->entries.begin(); it != m_mergeSetList[i]->entries.end(); ++it ) + for ( QValueList::ConstIterator fIt = ( *it )->begin(); fIt != ( *it )->end(); ++fIt ) + if ( newEntry->getField(( *fIt )->fieldTypeName() ) == NULL ) + { + newEntry->addField( new BibTeX::EntryField( *fIt ) ); + } + + for ( QValueList::Iterator it = m_mergeSetList[i]->entries.begin(); it != m_mergeSetList[i]->entries.end(); ++it ) + { + BibTeX::Entry *entry = dynamic_cast( bibTeXFile->containsKey(( *it )->id() ) ); + if ( entry != NULL ) + bibTeXFile->deleteElement( entry ); + else + { + BibTeX::Entry *entry = dynamic_cast( 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 ( QValueList::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 ( QValueList::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 ) ); + qDebug( "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 QDialog::Rejected; + } + + m_mergeSetList = new MergeSet*[m_duplicateCliqueList.size()]; + memset( m_mergeSetList, 0, sizeof( MergeSet* )*m_duplicateCliqueList.size() ); + + qDebug( "%i cliques", m_duplicateCliqueList.size() ); + setClique( 0 ); + + int result = exec(); + if ( result == QDialog::Accepted ) + applyMergeSet( bibTeXFile ); + + delete[] m_mergeSetList; + + return result; + } + + void MergeElements::slotRefreshAlternatives() + { + QMap mapFieldToController; + QMap firstEntryData; + bool first = true; + MergePreambleAlternativesController* preambleController = NULL; + MergeMacrosAlternativesController* macroKeyController = NULL; + MergeMacrosAlternativesController* macroValueController = NULL; + MergeEntriesAlternativesController *idController = NULL; + MergeEntriesAlternativesController *typeController = NULL; + QString firstId = QString::null; + QString firstMacroKey = QString::null; + BibTeX::Value *firstMacroValue = NULL; + QString firstPreambleText = QString::null; + BibTeX::Entry::EntryType firstType = BibTeX::Entry::etUnknown; + QString firstTypeString = QString::null; + + m_listViewAlternatives->clear(); + + for ( QListViewItemIterator it( m_listViewClique, QListViewItemIterator::Checked ); it.current(); ++it ) + { + MergeElementsCliqueItem *meci = dynamic_cast( *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 + { + QString thisText = entry->id(); + bool isNew = true; + for ( QListViewItem *cur = idController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() ) + { + MergeElementsAlternativesId *meai = dynamic_cast( 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 + { + QString typeString = entry->entryTypeString(); + BibTeX::Entry::EntryType type = entry->entryType(); + bool isNew = true; + for ( QListViewItem *cur = typeController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() ) + { + MergeEntriesAlternativesEntryType *meat = dynamic_cast( 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()]; + QString thisText = ( *efi )->value()->text(); + bool isNew = true; + for ( QListViewItem *cur = controller->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() ) + { + MergeEntriesAlternativesItem *meai = dynamic_cast( cur ); + isNew = meai->field->value()->text() != thisText; + } + if ( isNew ) + new MergeEntriesAlternativesItem( *efi, controller ); + } + else if ( firstEntryData.contains(( *efi )->fieldType() ) ) + { + QString firstText = firstEntryData[( *efi )->fieldType()].field->value()->text(); + QString 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 + { + QString thisText = macro->key(); + bool isNew = true; + for ( QListViewItem *cur = macroKeyController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() ) + { + MergeMacroAlternativesKey *mak = dynamic_cast( 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 + { + QString macroString = macro->value()->text(); + bool isNew = true; + for ( QListViewItem *cur = macroValueController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() ) + { + MergeMacrosAlternativesItem *mai = dynamic_cast( 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 + { + QString thisText = preamble->value()->text(); + bool isNew = true; + for ( QListViewItem *cur = preambleController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() ) + { + MergePreambleAlternatives *mpa = dynamic_cast( 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( QListViewItem *item ) + { + MergeElementsCliqueItem *meci = dynamic_cast( 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 KMainWindow of KDE 3.5 and modified to fit KBibTeX */ + void MergeElements::saveWindowSize( KConfig *config ) const + { + int scnum = QApplication::desktop()->screenNumber( parentWidget() ); + QRect desk = QApplication::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 + QRect size( desk.width(), w, desk.height(), h ); + bool defaultSize = false;//( size == d->defaultWindowSize ); + QString widthString = QString::fromLatin1( "Width %1" ).arg( desk.width() ); + QString heightString = QString::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( QShowEvent * ) + { + qDebug( "showEvent" ); + QTimer::singleShot( 10, this, SLOT( slotRestore() ) ); + } + + void MergeElements::slotRestore() + { + qDebug( "slotRestore" ); + KConfig * config = kapp->config(); + config->setGroup( "MergeElements" ); + restoreWindowSize( config ); + } + + /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */ + void MergeElements::restoreWindowSize( KConfig *config ) + { + // restore the size + int scnum = QApplication::desktop()->screenNumber( parentWidget() ); + QRect desk = QApplication::desktop()->screenGeometry( scnum ); + QSize size( config->readNumEntry( QString::fromLatin1( "Width %1" ).arg( desk.width() ), 0 ), + config->readNumEntry( QString::fromLatin1( "Height %1" ).arg( desk.height() ), 0 ) ); + if ( size.isEmpty() ) + { + // try the KDE 2.0 way + size = QSize( config->readNumEntry( QString::fromLatin1( "Width" ), 0 ), + config->readNumEntry( QString::fromLatin1( "Height" ), 0 ) ); + if ( !size.isEmpty() ) + { + // make sure the other resolutions don't get old settings + config->writeEntry( QString::fromLatin1( "Width" ), 0 ); + config->writeEntry( QString::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 ); + // QWidget::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" -- cgit v1.2.3