~ubuntu-branches/ubuntu/wily/kbibtex/wily

« back to all changes in this revision

Viewing changes to src/mergeelements.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2009-06-15 12:41:19 UTC
  • mfrom: (1.1.3 upstream) (2.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090615124119-eoojhlvkmw3o9tkm
Tags: 0.2.2-1
* New upstream version (Closes: #487301, #507837, #518959, #520392).
* Bumped Standards-Version to 3.8.1. No changes necessary.
* Added 'DM-Upload-Allowed: yes'.
* Added missing '${misc:Depends}'.
* Support for per-file encoding settings (Closes: #514356)
* Upgrade debhelper compatibility to version 5.
* Update debian/copyright for 2009 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2004-2009 by Thomas Fischer                             *
 
3
 *   fischer@unix-ag.uni-kl.de                                             *
 
4
 *                                                                         *
 
5
 *   This program is free software; you can redistribute it and/or modify  *
 
6
 *   it under the terms of the GNU General Public License as published by  *
 
7
 *   the Free Software Foundation; either version 2 of the License, or     *
 
8
 *   (at your option) any later version.                                   *
 
9
 *                                                                         *
 
10
 *   This program is distributed in the hope that it will be useful,       *
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
13
 *   GNU General Public License for more details.                          *
 
14
 *                                                                         *
 
15
 *   You should have received a copy of the GNU General Public License     *
 
16
 *   along with this program; if not, write to the                         *
 
17
 *   Free Software Foundation, Inc.,                                       *
 
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 
19
 ***************************************************************************/
 
20
#include <cmath>
 
21
 
 
22
#include <qlayout.h>
 
23
#include <qlabel.h>
 
24
#include <qprogressbar.h>
 
25
#include <qtimer.h>
 
26
 
 
27
#include <klocale.h>
 
28
#include <kpushbutton.h>
 
29
#include <kapplication.h>
 
30
#include <kmessagebox.h>
 
31
#include <ktextedit.h>
 
32
#include <klistview.h>
 
33
#include <kconfig.h>
 
34
#include <kwin.h>
 
35
 
 
36
#include <macro.h>
 
37
#include <comment.h>
 
38
#include <preamble.h>
 
39
#include <macrowidget.h>
 
40
#include <entrywidget.h>
 
41
#include <preamblewidget.h>
 
42
#include <settings.h>
 
43
#include <fileexporterbibtex.h>
 
44
#include "mergeelements.h"
 
45
 
 
46
namespace KBibTeX
 
47
{
 
48
    MergeElementsCliqueItem::MergeElementsCliqueItem( BibTeX::Entry* _entry, BibTeX::Macro* _macro, BibTeX::Preamble* _preamble, QListView *parent )
 
49
            : QCheckListItem( parent, _entry == NULL ?( _macro == NULL ? _preamble->value()->text() : _macro->key() ) : _entry->id(), QCheckListItem::CheckBox ), entry( _entry ), macro( _macro ), preamble( _preamble )
 
50
    {
 
51
        // nothing
 
52
    }
 
53
 
 
54
    void MergeElementsCliqueItem::stateChange( bool )
 
55
    {
 
56
        emit stateChanged( this );
 
57
    };
 
58
 
 
59
    MergeEntriesAlternativesController::MergeEntriesAlternativesController( const QString &label, QListView *parent )
 
60
            : QCheckListItem( parent, label, QCheckListItem::RadioButtonController ), fieldType( BibTeX::EntryField::ftUnknown ), fieldName( label )
 
61
    {
 
62
        // nothing
 
63
    }
 
64
 
 
65
    MergeEntriesAlternativesController::MergeEntriesAlternativesController( BibTeX::EntryField::FieldType _fieldType, QListView *parent )
 
66
            : QCheckListItem( parent, BibTeX::EntryField::fieldTypeToString( _fieldType ), QCheckListItem::RadioButtonController ), fieldType( _fieldType ), fieldName( BibTeX::EntryField::fieldTypeToString( _fieldType ) )
 
67
    {
 
68
        // nothing
 
69
    }
 
70
 
 
71
    MergeMacrosAlternativesController::MergeMacrosAlternativesController( bool isKey, QListView *parent )
 
72
            : QCheckListItem( parent, isKey ? i18n( "Key" ) : i18n( "Value" ), QCheckListItem::RadioButtonController )
 
73
    {
 
74
        // nothing
 
75
    }
 
76
 
 
77
    MergeEntriesAlternativesItem::MergeEntriesAlternativesItem( BibTeX::EntryField *_field, MergeEntriesAlternativesController *parent )
 
78
            : QCheckListItem( parent, _field->value()->text(), QCheckListItem::RadioButton ), field( _field )
 
79
    {
 
80
        // nothing
 
81
    }
 
82
 
 
83
    MergeMacrosAlternativesItem::MergeMacrosAlternativesItem( BibTeX::Value *_value, MergeMacrosAlternativesController *parent )
 
84
            : QCheckListItem( parent, _value->text(), QCheckListItem::RadioButton ), value( _value )
 
85
    {
 
86
        // nothing
 
87
    }
 
88
 
 
89
    MergeElementsAlternativesId::MergeElementsAlternativesId( const QString & _id, MergeEntriesAlternativesController *parent ) : QCheckListItem( parent, _id, QCheckListItem::RadioButton ), id( _id )
 
90
    {
 
91
        // nothing
 
92
    }
 
93
 
 
94
    MergeMacroAlternativesKey::MergeMacroAlternativesKey( const QString & _key, MergeMacrosAlternativesController *parent ) : QCheckListItem( parent, _key, QCheckListItem::RadioButton ), key( _key )
 
95
    {
 
96
        // nothing
 
97
    }
 
98
 
 
99
    MergeEntriesAlternativesEntryType::MergeEntriesAlternativesEntryType( const QString & _typeString, MergeEntriesAlternativesController *parent )
 
100
            : QCheckListItem( parent, _typeString, QCheckListItem::RadioButton ), typeString( _typeString ), type( BibTeX::Entry::entryTypeFromString( _typeString ) )
 
101
    {
 
102
        // nothing
 
103
    }
 
104
 
 
105
    MergeEntriesAlternativesEntryType::MergeEntriesAlternativesEntryType( BibTeX::Entry::EntryType _type, MergeEntriesAlternativesController *parent )
 
106
            : QCheckListItem( parent, BibTeX::Entry::entryTypeToString( _type ), QCheckListItem::RadioButton ), typeString( BibTeX::Entry::entryTypeToString( _type ) ), type( _type )
 
107
    {
 
108
        // nothing
 
109
    }
 
110
 
 
111
    MergePreambleAlternativesController::MergePreambleAlternativesController( QListView *parent )
 
112
            : QCheckListItem( parent, i18n( "Preamble text" ), QCheckListItem::RadioButtonController )
 
113
    {
 
114
        // nothing
 
115
    }
 
116
 
 
117
    MergePreambleAlternatives::MergePreambleAlternatives( const QString &_text, MergePreambleAlternativesController *parent )
 
118
            :QCheckListItem( parent, _text, QCheckListItem::RadioButton ), text( _text )
 
119
    {
 
120
        // nothing
 
121
    }
 
122
 
 
123
    MergeElements::MergeElements( QWidget *parent )
 
124
            : KDialogBase( parent, "MergeElements", true, "undefined", Ok | Cancel | User1 | User2, User1, true, KGuiItem( i18n( "Next" ), "next" ), KGuiItem( i18n( "Previous" ), "previous" ) ), m_currentCliqueIndex( 0 )
 
125
    {
 
126
        setupGUI();
 
127
    }
 
128
 
 
129
    MergeElements::~MergeElements()
 
130
    {
 
131
        KConfig * config = kapp->config();
 
132
        config->setGroup( "MergeElements" );
 
133
        saveWindowSize( config );
 
134
    }
 
135
 
 
136
    void MergeElements::setupGUI()
 
137
    {
 
138
        QWidget *vboxContainer = new QWidget( this );
 
139
        setMainWidget( vboxContainer );
 
140
        QBoxLayout *vboxLayout = new QVBoxLayout( vboxContainer, 0, KDialog::spacingHint() );
 
141
        vboxLayout->setResizeMode( QLayout::Minimum );
 
142
 
 
143
        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 );
 
144
        label->setAlignment( Qt::WordBreak );
 
145
        vboxLayout->addWidget( label );
 
146
        m_listViewClique = new KListView( vboxContainer );
 
147
        m_listViewClique->addColumn( i18n( "Entry/Macro Id" ) );
 
148
        m_listViewClique->setFullWidth( true );
 
149
        m_listViewClique->setAllColumnsShowFocus( true );
 
150
        vboxLayout->addWidget( m_listViewClique );
 
151
        vboxLayout->setStretchFactor( m_listViewClique, 1 );
 
152
        label->setBuddy( m_listViewClique );
 
153
 
 
154
        m_progressBar = new QProgressBar( vboxContainer );
 
155
        vboxLayout->addWidget( m_progressBar );
 
156
 
 
157
        vboxLayout->addSpacing( KDialog::spacingHint() * 2 );
 
158
 
 
159
        label = new QLabel( i18n( "Choose from this list which alternatives you want to keep in the merged element." ), vboxContainer );
 
160
        label->setAlignment( Qt::WordBreak );
 
161
        vboxLayout->addWidget( label );
 
162
        m_listViewAlternatives = new KListView( vboxContainer );
 
163
        m_listViewAlternatives->addColumn( i18n( "Field/Key" ) );
 
164
        m_listViewAlternatives->setFullWidth( true );
 
165
        m_listViewAlternatives->setAllColumnsShowFocus( true );
 
166
        vboxLayout->addWidget( m_listViewAlternatives );
 
167
        vboxLayout->setStretchFactor( m_listViewAlternatives, 3 );
 
168
        label->setBuddy( m_listViewAlternatives );
 
169
 
 
170
        connect( m_listViewClique, SIGNAL( doubleClicked( QListViewItem * ) ), this, SLOT( slotPreviewElement( QListViewItem * ) ) );
 
171
        connect( this, SIGNAL( user1Clicked() ), this, SLOT( slotNextClique() ) );
 
172
        connect( this, SIGNAL( user2Clicked() ), this, SLOT( slotPreviousClique() ) );
 
173
        connect( this, SIGNAL( okClicked() ), this, SLOT( saveCurrentMergeSet() ) );
 
174
    }
 
175
 
 
176
    void MergeElements::setClique( int cliqueIndex )
 
177
    {
 
178
        if ( m_currentCliqueIndex != cliqueIndex )
 
179
            saveCurrentMergeSet();
 
180
        m_currentCliqueIndex = cliqueIndex;
 
181
 
 
182
        m_listViewClique->clear();
 
183
        FindDuplicates::DuplicateClique clique = m_duplicateCliqueList[cliqueIndex];
 
184
 
 
185
        for ( FindDuplicates::DuplicateClique::Iterator it = clique.begin(); it != clique.end(); ++it )
 
186
        {
 
187
            BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( *it );
 
188
            if ( entry != NULL )
 
189
            {
 
190
                MergeElementsCliqueItem *item = new MergeElementsCliqueItem( entry, NULL, NULL, m_listViewClique );
 
191
                connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
 
192
            }
 
193
            else
 
194
            {
 
195
                BibTeX::Macro *macro = dynamic_cast<BibTeX::Macro*>( *it );
 
196
                if ( macro != NULL )
 
197
                {
 
198
                    MergeElementsCliqueItem *item = new MergeElementsCliqueItem( NULL, macro, NULL, m_listViewClique );
 
199
                    connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
 
200
                }
 
201
                else
 
202
                {
 
203
                    BibTeX::Preamble *preamble = dynamic_cast<BibTeX::Preamble*>( *it );
 
204
                    if ( preamble!=NULL )
 
205
                    {
 
206
                        MergeElementsCliqueItem *item = new MergeElementsCliqueItem( NULL, NULL, preamble, m_listViewClique );
 
207
                        connect( item, SIGNAL( stateChanged( MergeElementsCliqueItem* ) ), this, SLOT( slotRefreshAlternatives() ) );
 
208
                    }
 
209
                }
 
210
            }
 
211
        }
 
212
        restoreCurrentMergeSet();
 
213
 
 
214
        enableButton( User1, ( cliqueIndex < ( int )( m_duplicateCliqueList.size() ) - 1 ) && m_duplicateCliqueList.size() > 1 );
 
215
        enableButton( User2, cliqueIndex > 0 && m_duplicateCliqueList.size() > 1 );
 
216
        m_progressBar->setProgress( cliqueIndex, m_duplicateCliqueList.size() - 1 );
 
217
    }
 
218
 
 
219
    void MergeElements::saveCurrentMergeSet()
 
220
    {
 
221
        if ( m_mergeSetList[m_currentCliqueIndex] == NULL )
 
222
            m_mergeSetList[m_currentCliqueIndex] = new MergeSet;
 
223
        else
 
224
        {
 
225
            m_mergeSetList[m_currentCliqueIndex]->entries.clear();
 
226
            m_mergeSetList[m_currentCliqueIndex]->fields.clear();
 
227
        }
 
228
        m_mergeSetList[m_currentCliqueIndex]->type = BibTeX::Entry::etUnknown;
 
229
        m_mergeSetList[m_currentCliqueIndex]->typeString = QString::null;
 
230
        m_mergeSetList[m_currentCliqueIndex]->id = QString::null;
 
231
        m_mergeSetList[m_currentCliqueIndex]->macroKey = QString::null;
 
232
        m_mergeSetList[m_currentCliqueIndex]->macroValue = NULL;
 
233
        m_mergeSetList[m_currentCliqueIndex]->preambleText=QString::null;
 
234
 
 
235
        for ( QListViewItemIterator it( m_listViewClique, QListViewItemIterator::Checked ); it.current(); ++it )
 
236
        {
 
237
            MergeElementsCliqueItem *eci = dynamic_cast<MergeElementsCliqueItem*>( *it );
 
238
            BibTeX::Entry *entry = eci->entry;
 
239
            if ( entry != NULL )
 
240
                m_mergeSetList[m_currentCliqueIndex]->entries.append( entry );
 
241
            BibTeX::Macro *macro = eci->macro;
 
242
            if ( macro != NULL )
 
243
                m_mergeSetList[m_currentCliqueIndex]->macros.append( macro );
 
244
            BibTeX::Preamble *preamble = eci->preamble;
 
245
            if ( preamble !=NULL )
 
246
                m_mergeSetList[m_currentCliqueIndex]->preambles.append( preamble );
 
247
        }
 
248
 
 
249
        for ( QListViewItemIterator it( m_listViewAlternatives, QListViewItemIterator::Checked ); it.current(); ++it )
 
250
        {
 
251
            MergeEntriesAlternativesItem *item = dynamic_cast<MergeEntriesAlternativesItem*>( *it );
 
252
            if ( item != NULL )
 
253
            {
 
254
                BibTeX::EntryField *field = item->field;
 
255
                m_mergeSetList[m_currentCliqueIndex]->fields.append( field );
 
256
            }
 
257
            else
 
258
            {
 
259
                MergeElementsAlternativesId *item = dynamic_cast<MergeElementsAlternativesId*>( *it );
 
260
                if ( item != NULL )
 
261
                    m_mergeSetList[m_currentCliqueIndex]->id = item->id;
 
262
                else
 
263
                {
 
264
                    MergeEntriesAlternativesEntryType *itemT = dynamic_cast<MergeEntriesAlternativesEntryType*>( *it );
 
265
                    if ( itemT != NULL )
 
266
                    {
 
267
                        m_mergeSetList[m_currentCliqueIndex]->typeString = itemT->typeString;
 
268
                        m_mergeSetList[m_currentCliqueIndex]->type = itemT->type;
 
269
                    }
 
270
                    else
 
271
                    {
 
272
                        MergeMacroAlternativesKey *itemK = dynamic_cast<MergeMacroAlternativesKey*>( *it );
 
273
                        if ( itemK != NULL )
 
274
                            m_mergeSetList[m_currentCliqueIndex]->macroKey = itemK->key;
 
275
                        else
 
276
                        {
 
277
                            MergeMacrosAlternativesItem *itemMA = dynamic_cast<MergeMacrosAlternativesItem*>( *it );
 
278
                            if ( itemMA != NULL )
 
279
                                m_mergeSetList[m_currentCliqueIndex]->macroValue = itemMA->value;
 
280
                            else
 
281
                            {
 
282
                                MergePreambleAlternatives *itemP=dynamic_cast<MergePreambleAlternatives*>( *it );
 
283
                                if ( itemP!=NULL )
 
284
                                    m_mergeSetList[m_currentCliqueIndex]->preambleText=itemP->text;
 
285
                            }
 
286
                        }
 
287
                    }
 
288
                }
 
289
            }
 
290
        }
 
291
    }
 
292
 
 
293
    void MergeElements::restoreCurrentMergeSet()
 
294
    {
 
295
        if ( m_mergeSetList[m_currentCliqueIndex] == NULL )
 
296
        {
 
297
            m_listViewAlternatives->clear();
 
298
            return;
 
299
        }
 
300
 
 
301
        for ( QListViewItemIterator it( m_listViewClique ); it.current(); ++it )
 
302
        {
 
303
            MergeElementsCliqueItem *item = dynamic_cast<MergeElementsCliqueItem*>( *it );
 
304
            BibTeX::Entry *entry = item->entry;
 
305
            BibTeX::Macro *macro = item->macro;
 
306
            BibTeX::Preamble *preamble = item->preamble;
 
307
            if ( entry != NULL )
 
308
                for ( QValueList<BibTeX::Entry*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->entries.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->entries.end(); ++it2 )
 
309
                {
 
310
                    if ( entry->id() == ( *it2 )->id() )
 
311
                    {
 
312
                        item->setOn( true );
 
313
                        break;
 
314
                    }
 
315
                }
 
316
            else if ( macro != NULL )
 
317
            {
 
318
                for ( QValueList<BibTeX::Macro*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->macros.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->macros.end(); ++it2 )
 
319
                    if ( macro->key() == ( *it2 )->key() )
 
320
                    {
 
321
                        item->setOn( true );
 
322
                        break;
 
323
                    }
 
324
            }
 
325
            else if ( preamble!=NULL )
 
326
                for ( QValueList<BibTeX::Preamble*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->preambles.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->preambles.end(); ++it2 )
 
327
                    if ( preamble->value()->text() == ( *it2 )->value()->text() )
 
328
                    {
 
329
                        item->setOn( true );
 
330
                        break;
 
331
                    }
 
332
        }
 
333
 
 
334
        slotRefreshAlternatives();
 
335
 
 
336
        for ( QListViewItemIterator it( m_listViewAlternatives ); it.current(); ++it )
 
337
        {
 
338
            MergeEntriesAlternativesItem *item = dynamic_cast<MergeEntriesAlternativesItem*>( *it );
 
339
            if ( item != NULL )
 
340
            {
 
341
                for ( QValueList<BibTeX::EntryField*>::Iterator it2 = m_mergeSetList[m_currentCliqueIndex]->fields.begin(); it2 != m_mergeSetList[m_currentCliqueIndex]->fields.end(); ++it2 )
 
342
                    if ( item->field->fieldTypeName().lower() == ( *it2 )->fieldTypeName().lower() &&  item->field->value()->text() == ( *it2 )->value()->text() )
 
343
                    {
 
344
                        item->setOn( true );
 
345
                        break;
 
346
                    }
 
347
            }
 
348
            else
 
349
            {
 
350
                MergeElementsAlternativesId *item = dynamic_cast<MergeElementsAlternativesId*>( *it );
 
351
                if ( item != NULL )
 
352
                {
 
353
                    if ( item->id == m_mergeSetList[m_currentCliqueIndex]->id )
 
354
                        item->setOn( true );
 
355
                }
 
356
                else
 
357
                {
 
358
                    MergeEntriesAlternativesEntryType *item = dynamic_cast<MergeEntriesAlternativesEntryType*>( *it );
 
359
                    if ( item != NULL )
 
360
                    {
 
361
                        if (( item->type != BibTeX::Entry::etUnknown && item->type == m_mergeSetList[m_currentCliqueIndex]->type ) || ( item->typeString.lower() == m_mergeSetList[m_currentCliqueIndex]->typeString.lower() ) )
 
362
                            item->setOn( true );
 
363
                    }
 
364
                    else
 
365
                    {
 
366
                        MergeMacrosAlternativesItem *mai = dynamic_cast<MergeMacrosAlternativesItem*>( *it );
 
367
                        if ( mai != NULL )
 
368
                        {
 
369
                            if ( mai->value == m_mergeSetList[m_currentCliqueIndex]->macroValue )
 
370
                                mai->setOn( true );
 
371
                        }
 
372
                        else
 
373
                        {
 
374
                            MergeMacroAlternativesKey *mak = dynamic_cast<MergeMacroAlternativesKey*>( *it );
 
375
                            if ( mak != NULL )
 
376
                            {
 
377
                                if ( mak->key == m_mergeSetList[m_currentCliqueIndex]->macroKey )
 
378
                                    mak->setOn( true );
 
379
                            }
 
380
                            else
 
381
                            {
 
382
                                MergePreambleAlternatives *mpa =dynamic_cast<MergePreambleAlternatives*>( *it );
 
383
                                if ( mpa!=NULL )
 
384
                                {
 
385
                                    if ( mpa->text==m_mergeSetList[m_currentCliqueIndex]->preambleText )
 
386
                                        mpa->setOn( true );
 
387
                                }
 
388
                                else
 
389
                                    qDebug( "Item is of unknown type" );
 
390
                            }
 
391
                        }
 
392
                    }
 
393
                }
 
394
            }
 
395
        }
 
396
    }
 
397
 
 
398
    void MergeElements::applyMergeSet( BibTeX::File *bibTeXFile, BibTeX::File *otherBibTeXFile )
 
399
    {
 
400
        int n = m_duplicateCliqueList.size();
 
401
        for ( int i = 0; i < n; ++i )
 
402
        {
 
403
            if ( m_mergeSetList[i] == NULL ) continue;
 
404
 
 
405
            if ( !m_mergeSetList[i]->entries.isEmpty() )
 
406
            {
 
407
                QString id = m_mergeSetList[i]->id == QString::null ? ( *m_mergeSetList[i]->entries.begin() )->id() : m_mergeSetList[i]->id;
 
408
 
 
409
                BibTeX::Entry *newEntry = NULL;
 
410
                if ( m_mergeSetList[i]->type == BibTeX::Entry::etUnknown )
 
411
                {
 
412
                    if ( m_mergeSetList[i]->typeString == QString::null )
 
413
                    {
 
414
                        BibTeX::Entry *firstEntry = *m_mergeSetList[i]->entries.begin();
 
415
                        if ( firstEntry->entryType() == BibTeX::Entry::etUnknown )
 
416
                            newEntry = new BibTeX::Entry( firstEntry->entryTypeString(), id );
 
417
                        else
 
418
                            newEntry = new BibTeX::Entry( firstEntry->entryType(), id );
 
419
                    }
 
420
                    else
 
421
                        newEntry = new BibTeX::Entry( m_mergeSetList[i]->typeString, id );
 
422
                }
 
423
                else
 
424
                    newEntry = new BibTeX::Entry( m_mergeSetList[i]->type, id );
 
425
 
 
426
                for ( QValueList<BibTeX::EntryField*>::Iterator it = m_mergeSetList[i]->fields.begin(); it != m_mergeSetList[i]->fields.end(); ++it )
 
427
                {
 
428
                    newEntry->addField( new BibTeX::EntryField( *it ) );
 
429
                }
 
430
 
 
431
                for ( QValueList<BibTeX::Entry*>::Iterator it = m_mergeSetList[i]->entries.begin(); it != m_mergeSetList[i]->entries.end(); ++it )
 
432
                    for ( QValueList<BibTeX::EntryField*>::ConstIterator fIt = ( *it )->begin(); fIt != ( *it )->end(); ++fIt )
 
433
                        if ( newEntry->getField(( *fIt )->fieldTypeName() ) == NULL )
 
434
                        {
 
435
                            newEntry->addField( new BibTeX::EntryField( *fIt ) );
 
436
                        }
 
437
 
 
438
                for ( QValueList<BibTeX::Entry*>::Iterator it = m_mergeSetList[i]->entries.begin(); it != m_mergeSetList[i]->entries.end(); ++it )
 
439
                {
 
440
                    BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( bibTeXFile->containsKey(( *it )->id() ) );
 
441
                    if ( entry != NULL )
 
442
                        bibTeXFile->deleteElement( entry );
 
443
                    else
 
444
                    {
 
445
                        BibTeX::Entry *entry = dynamic_cast<BibTeX::Entry*>( otherBibTeXFile->containsKey(( *it )->id() ) );
 
446
                        if ( entry != NULL )
 
447
                            otherBibTeXFile->deleteElement( entry );
 
448
                    }
 
449
                }
 
450
                bibTeXFile->appendElement( newEntry );
 
451
            }
 
452
            else if ( !m_mergeSetList[i]->macros.isEmpty() )
 
453
            {
 
454
                BibTeX::Macro *newMacro = new BibTeX::Macro( m_mergeSetList[i]->macroKey );
 
455
                newMacro->setValue( m_mergeSetList[i]->macroValue );
 
456
 
 
457
                for ( QValueList<BibTeX::Macro*>::Iterator it = m_mergeSetList[i]->macros.begin(); it != m_mergeSetList[i]->macros.end(); ++it )
 
458
                {
 
459
                    bibTeXFile->deleteElement( *it );
 
460
                    if ( otherBibTeXFile != NULL )
 
461
                        otherBibTeXFile->deleteElement( *it );
 
462
                }
 
463
 
 
464
                bibTeXFile->appendElement( newMacro );
 
465
            }
 
466
            else if ( !m_mergeSetList[i]->preambles.isEmpty() )
 
467
            {
 
468
                BibTeX::Preamble *newPreamble = new BibTeX::Preamble( m_mergeSetList[i]->preambleText );
 
469
 
 
470
                for ( QValueList<BibTeX::Preamble*>::Iterator it = m_mergeSetList[i]->preambles.begin(); it != m_mergeSetList[i]->preambles.end(); ++it )
 
471
                {
 
472
                    bibTeXFile->deleteElement( *it );
 
473
                    if ( otherBibTeXFile != NULL )
 
474
                        otherBibTeXFile->deleteElement( *it );
 
475
                }
 
476
 
 
477
                bibTeXFile->appendElement( newPreamble );
 
478
            }
 
479
        }
 
480
    }
 
481
 
 
482
    int MergeElements::mergeDuplicates( BibTeX::File *bibTeXFile )
 
483
    {
 
484
        setCaption( i18n( "Find Duplicates" ) );
 
485
        Settings * settings = Settings::self( NULL );
 
486
        int sensitivity = ( int )( FindDuplicates::maxDistance / exp( log( 10 ) * settings->editing_findDuplicatesSensitivity / 10.0 ) );
 
487
        qDebug( "sensitivity= %i / %i", sensitivity, FindDuplicates::maxDistance );
 
488
        FindDuplicates findDuplicates( m_duplicateCliqueList, sensitivity, bibTeXFile, parentWidget( true ) );
 
489
 
 
490
        if ( m_duplicateCliqueList.isEmpty() )
 
491
        {
 
492
            KMessageBox::information( parentWidget( true ), i18n( "No duplicates found." ), i18n( "Find Duplicates" ) );
 
493
            return QDialog::Rejected;
 
494
        }
 
495
 
 
496
        m_mergeSetList = new MergeSet*[m_duplicateCliqueList.size()];
 
497
        memset( m_mergeSetList, 0, sizeof( MergeSet* )*m_duplicateCliqueList.size() );
 
498
 
 
499
        qDebug( "%i cliques", m_duplicateCliqueList.size() );
 
500
        setClique( 0 );
 
501
 
 
502
        int result = exec();
 
503
        if ( result == QDialog::Accepted )
 
504
            applyMergeSet( bibTeXFile );
 
505
 
 
506
        delete[] m_mergeSetList;
 
507
 
 
508
        return result;
 
509
    }
 
510
 
 
511
    void MergeElements::slotRefreshAlternatives()
 
512
    {
 
513
        QMap<BibTeX::EntryField::FieldType, MergeEntriesAlternativesController*> mapFieldToController;
 
514
        QMap<BibTeX::EntryField::FieldType, First> firstEntryData;
 
515
        bool first = true;
 
516
        MergePreambleAlternativesController* preambleController = NULL;
 
517
        MergeMacrosAlternativesController* macroKeyController = NULL;
 
518
        MergeMacrosAlternativesController* macroValueController = NULL;
 
519
        MergeEntriesAlternativesController *idController = NULL;
 
520
        MergeEntriesAlternativesController *typeController = NULL;
 
521
        QString firstId = QString::null;
 
522
        QString firstMacroKey = QString::null;
 
523
        BibTeX::Value *firstMacroValue = NULL;
 
524
        QString firstPreambleText = QString::null;
 
525
        BibTeX::Entry::EntryType firstType = BibTeX::Entry::etUnknown;
 
526
        QString firstTypeString = QString::null;
 
527
 
 
528
        m_listViewAlternatives->clear();
 
529
 
 
530
        for ( QListViewItemIterator it( m_listViewClique, QListViewItemIterator::Checked ); it.current(); ++it )
 
531
        {
 
532
            MergeElementsCliqueItem *meci = dynamic_cast<MergeElementsCliqueItem*>( *it );
 
533
            BibTeX::Entry *entry = NULL;
 
534
            BibTeX::Macro *macro = NULL;
 
535
            BibTeX::Preamble *preamble = NULL;
 
536
            if ( meci != NULL && ( entry = meci->entry ) != NULL )
 
537
            {
 
538
                if ( first )
 
539
                {
 
540
                    firstId = entry->id();
 
541
                    firstType = entry->entryType();
 
542
                    firstTypeString = entry->entryTypeString();
 
543
                    for ( BibTeX::Entry::EntryFields::const_iterator efi = entry->begin(); efi != entry->end(); ++efi )
 
544
                    {
 
545
                        First first;
 
546
                        first.entry = entry;
 
547
                        first.field = *efi;
 
548
                        firstEntryData.insert(( *efi )->fieldType(), first );
 
549
                    }
 
550
                }
 
551
                else
 
552
                {
 
553
                    if ( idController == NULL )
 
554
                    {
 
555
                        if ( entry->id() != firstId )
 
556
                        {
 
557
                            idController = new MergeEntriesAlternativesController( i18n( "Id" ), m_listViewAlternatives );
 
558
                            idController->setOpen( true );
 
559
                            MergeElementsAlternativesId *item = new MergeElementsAlternativesId( firstId, idController );
 
560
                            item->setOn( true );
 
561
                            new MergeElementsAlternativesId( entry->id(), idController );
 
562
                        }
 
563
                    }
 
564
                    else
 
565
                    {
 
566
                        QString thisText = entry->id();
 
567
                        bool isNew = true;
 
568
                        for ( QListViewItem *cur = idController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
 
569
                        {
 
570
                            MergeElementsAlternativesId *meai = dynamic_cast<MergeElementsAlternativesId*>( cur );
 
571
                            isNew = meai->id != thisText;
 
572
                        }
 
573
                        if ( isNew )
 
574
                            new MergeElementsAlternativesId( thisText, idController );
 
575
                    }
 
576
 
 
577
                    if ( typeController == NULL )
 
578
                    {
 
579
                        if (( firstType != BibTeX::Entry::etUnknown && entry->entryType() != firstType ) || ( entry->entryTypeString().lower() != entry->entryTypeString().lower() ) )
 
580
                        {
 
581
                            typeController = new MergeEntriesAlternativesController( i18n( "Type" ), m_listViewAlternatives );
 
582
                            typeController->setOpen( true );
 
583
                            MergeEntriesAlternativesEntryType *item = firstType != BibTeX::Entry::etUnknown ? new MergeEntriesAlternativesEntryType( firstType, typeController ) : new MergeEntriesAlternativesEntryType( firstTypeString, typeController );
 
584
                            item->setOn( true );
 
585
                            if ( entry->entryType() != BibTeX::Entry::etUnknown )
 
586
                                new MergeEntriesAlternativesEntryType( entry->entryType(), typeController );
 
587
                            else
 
588
                                new MergeEntriesAlternativesEntryType( entry->entryTypeString(), typeController );
 
589
                        }
 
590
                    }
 
591
                    else
 
592
                    {
 
593
                        QString typeString = entry->entryTypeString();
 
594
                        BibTeX::Entry::EntryType type = entry->entryType();
 
595
                        bool isNew = true;
 
596
                        for ( QListViewItem *cur = typeController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
 
597
                        {
 
598
                            MergeEntriesAlternativesEntryType *meat = dynamic_cast<MergeEntriesAlternativesEntryType*>( cur );
 
599
                            isNew = type == BibTeX::Entry::etUnknown && meat->typeString != typeString || meat->type != type;
 
600
                        }
 
601
                        if ( isNew )
 
602
                        {
 
603
                            if ( type != BibTeX::Entry::etUnknown )
 
604
                                new MergeEntriesAlternativesEntryType( type, typeController );
 
605
                            else
 
606
                                new MergeEntriesAlternativesEntryType( typeString, typeController );
 
607
                        }
 
608
                    }
 
609
 
 
610
                    for ( BibTeX::Entry::EntryFields::const_iterator efi = entry->begin(); efi != entry->end(); ++efi )
 
611
                        if ( mapFieldToController.contains(( *efi )->fieldType() ) )
 
612
                        {
 
613
                            MergeEntriesAlternativesController *controller = mapFieldToController[( *efi )->fieldType()];
 
614
                            QString thisText = ( *efi )->value()->text();
 
615
                            bool isNew = true;
 
616
                            for ( QListViewItem *cur = controller->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
 
617
                            {
 
618
                                MergeEntriesAlternativesItem *meai = dynamic_cast<MergeEntriesAlternativesItem*>( cur );
 
619
                                isNew = meai->field->value()->text() != thisText;
 
620
                            }
 
621
                            if ( isNew )
 
622
                                new MergeEntriesAlternativesItem( *efi, controller );
 
623
                        }
 
624
                        else if ( firstEntryData.contains(( *efi )->fieldType() ) )
 
625
                        {
 
626
                            QString firstText = firstEntryData[( *efi )->fieldType()].field->value()->text();
 
627
                            QString thisText = ( *efi )->value()->text();
 
628
                            if ( firstText != thisText )
 
629
                            {
 
630
                                MergeEntriesAlternativesController *controller = new MergeEntriesAlternativesController(( *efi )->fieldType(), m_listViewAlternatives );
 
631
                                controller->setOpen( true );
 
632
                                MergeEntriesAlternativesItem *item = new MergeEntriesAlternativesItem( firstEntryData[( *efi )->fieldType()].field, controller );
 
633
                                item->setOn( true );
 
634
                                item = new MergeEntriesAlternativesItem( *efi, controller );
 
635
                                mapFieldToController.insert(( *efi )->fieldType(), controller );
 
636
                            }
 
637
                        }
 
638
                        else
 
639
                        {
 
640
                            First first;
 
641
                            first.entry = entry;
 
642
                            first.field = *efi;
 
643
                            firstEntryData.insert(( *efi )->fieldType(), first );
 
644
                        }
 
645
                }
 
646
            }
 
647
            else if ( meci != NULL && ( macro = meci->macro ) != NULL )
 
648
            {
 
649
                if ( first )
 
650
                {
 
651
                    firstMacroKey = macro->key();
 
652
                    firstMacroValue = macro->value();
 
653
                }
 
654
                else
 
655
                {
 
656
                    if ( macroKeyController == NULL )
 
657
                    {
 
658
                        if ( macro->key() != firstMacroKey )
 
659
                        {
 
660
                            macroKeyController = new MergeMacrosAlternativesController( true, m_listViewAlternatives );
 
661
                            macroKeyController->setOpen( true );
 
662
                            MergeMacroAlternativesKey *item = new MergeMacroAlternativesKey( firstMacroKey, macroKeyController );
 
663
                            item->setOn( true );
 
664
                            new MergeMacroAlternativesKey( macro->key(), macroKeyController );
 
665
                        }
 
666
                    }
 
667
                    else
 
668
                    {
 
669
                        QString thisText = macro->key();
 
670
                        bool isNew = true;
 
671
                        for ( QListViewItem *cur = macroKeyController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
 
672
                        {
 
673
                            MergeMacroAlternativesKey *mak = dynamic_cast<MergeMacroAlternativesKey*>( cur );
 
674
                            isNew = mak->key != thisText;
 
675
                        }
 
676
                        if ( isNew )
 
677
                            new MergeMacroAlternativesKey( thisText, macroKeyController );
 
678
                    }
 
679
                }
 
680
 
 
681
                if ( macroValueController == NULL )
 
682
                {
 
683
                    if ( firstMacroValue->text() != macro->value()->text() )
 
684
                    {
 
685
                        macroValueController = new MergeMacrosAlternativesController( false, m_listViewAlternatives );
 
686
                        macroValueController->setOpen( true );
 
687
                        MergeMacrosAlternativesItem *item = new MergeMacrosAlternativesItem( firstMacroValue, macroValueController );
 
688
                        item->setOn( true );
 
689
                        new MergeMacrosAlternativesItem( macro->value(), macroValueController );
 
690
                    }
 
691
                }
 
692
                else
 
693
                {
 
694
                    QString macroString = macro->value()->text();
 
695
                    bool isNew = true;
 
696
                    for ( QListViewItem *cur = macroValueController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
 
697
                    {
 
698
                        MergeMacrosAlternativesItem *mai = dynamic_cast<MergeMacrosAlternativesItem*>( cur );
 
699
                        isNew = macroString != mai->value->text();
 
700
                    }
 
701
                    if ( isNew )
 
702
                        new MergeMacrosAlternativesItem( macro->value(), macroValueController );
 
703
                }
 
704
            }
 
705
            else if ( meci != NULL && ( preamble = meci->preamble ) != NULL )
 
706
            {
 
707
                if ( first )
 
708
                    firstPreambleText = preamble->value()->text();
 
709
                else
 
710
                {
 
711
                    if ( preambleController == NULL )
 
712
                    {
 
713
                        if ( preamble->value()->text() != firstPreambleText )
 
714
                        {
 
715
                            preambleController = new MergePreambleAlternativesController( m_listViewAlternatives );
 
716
                            preambleController->setOpen( true );
 
717
                            MergePreambleAlternatives *item = new MergePreambleAlternatives( firstPreambleText, preambleController );
 
718
                            item->setOn( true );
 
719
                            new MergePreambleAlternatives( preamble->value()->text(), preambleController );
 
720
                        }
 
721
                    }
 
722
                    else
 
723
                    {
 
724
                        QString thisText = preamble->value()->text();
 
725
                        bool isNew = true;
 
726
                        for ( QListViewItem *cur = preambleController->firstChild(); isNew && cur != NULL; cur = cur->nextSibling() )
 
727
                        {
 
728
                            MergePreambleAlternatives *mpa = dynamic_cast<MergePreambleAlternatives*>( cur );
 
729
                            isNew = mpa->text != thisText;
 
730
                        }
 
731
                        if ( isNew )
 
732
                            new MergePreambleAlternatives( thisText, preambleController );
 
733
                    }
 
734
                }
 
735
            }
 
736
            first = false;
 
737
        }
 
738
    }
 
739
 
 
740
    void MergeElements::slotNextClique()
 
741
    {
 
742
        if ( m_currentCliqueIndex < ( int )( m_duplicateCliqueList.size() ) - 1 )
 
743
        {
 
744
            setClique( m_currentCliqueIndex + 1 );
 
745
        }
 
746
        else
 
747
            enableButton( User1, false );
 
748
    }
 
749
 
 
750
    void MergeElements::slotPreviousClique()
 
751
    {
 
752
        if ( m_currentCliqueIndex > 0 )
 
753
        {
 
754
            setClique( m_currentCliqueIndex - 1 );
 
755
        }
 
756
        else
 
757
            enableButton( User2, false );
 
758
    }
 
759
 
 
760
    void MergeElements::slotPreviewElement( QListViewItem *item )
 
761
    {
 
762
        MergeElementsCliqueItem *meci = dynamic_cast<MergeElementsCliqueItem*>( item );
 
763
        if ( meci != NULL && meci->entry != NULL )
 
764
            KBibTeX::EntryWidget::execute( meci->entry, NULL, TRUE, FALSE, this );
 
765
        else if ( meci != NULL && meci->macro != NULL )
 
766
            KBibTeX::MacroWidget::execute( meci->macro, TRUE, this );
 
767
        else if ( meci!=NULL&& meci->preamble!=NULL )
 
768
            KBibTeX::PreambleWidget::execute( meci->preamble, TRUE, this );
 
769
    }
 
770
 
 
771
    /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
 
772
    void MergeElements::saveWindowSize( KConfig *config ) const
 
773
    {
 
774
        int scnum = QApplication::desktop()->screenNumber( parentWidget() );
 
775
        QRect desk = QApplication::desktop()->screenGeometry( scnum );
 
776
        int w, h;
 
777
#if defined Q_WS_X11
 
778
        // save maximalization as desktop size + 1 in that direction
 
779
        KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState );
 
780
        w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
 
781
        h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
 
782
#else
 
783
        if ( isMaximized() )
 
784
        {
 
785
            w = desk.width() + 1;
 
786
            h = desk.height() + 1;
 
787
        }
 
788
        //TODO: add "Maximized" property instead "+1" hack
 
789
#endif
 
790
        QRect size( desk.width(), w, desk.height(), h );
 
791
        bool defaultSize = false;//( size == d->defaultWindowSize );
 
792
        QString widthString = QString::fromLatin1( "Width %1" ).arg( desk.width() );
 
793
        QString heightString = QString::fromLatin1( "Height %1" ).arg( desk.height() );
 
794
        if ( !config->hasDefault( widthString ) && defaultSize )
 
795
            config->revertToDefault( widthString );
 
796
        else
 
797
            config->writeEntry( widthString, w );
 
798
 
 
799
        if ( !config->hasDefault( heightString ) && defaultSize )
 
800
            config->revertToDefault( heightString );
 
801
        else
 
802
            config->writeEntry( heightString, h );
 
803
    }
 
804
 
 
805
    void MergeElements::showEvent( QShowEvent * )
 
806
    {
 
807
        qDebug( "showEvent" );
 
808
        QTimer::singleShot( 10, this, SLOT( slotRestore() ) );
 
809
    }
 
810
 
 
811
    void MergeElements::slotRestore()
 
812
    {
 
813
        qDebug( "slotRestore" );
 
814
        KConfig * config = kapp->config();
 
815
        config->setGroup( "MergeElements" );
 
816
        restoreWindowSize( config );
 
817
    }
 
818
 
 
819
    /* This function was taken form KMainWindow of KDE 3.5 and modified to fit KBibTeX */
 
820
    void MergeElements::restoreWindowSize( KConfig *config )
 
821
    {
 
822
        // restore the size
 
823
        int scnum = QApplication::desktop()->screenNumber( parentWidget() );
 
824
        QRect desk = QApplication::desktop()->screenGeometry( scnum );
 
825
        QSize size( config->readNumEntry( QString::fromLatin1( "Width %1" ).arg( desk.width() ), 0 ),
 
826
                    config->readNumEntry( QString::fromLatin1( "Height %1" ).arg( desk.height() ), 0 ) );
 
827
        if ( size.isEmpty() )
 
828
        {
 
829
            // try the KDE 2.0 way
 
830
            size = QSize( config->readNumEntry( QString::fromLatin1( "Width" ), 0 ),
 
831
                          config->readNumEntry( QString::fromLatin1( "Height" ), 0 ) );
 
832
            if ( !size.isEmpty() )
 
833
            {
 
834
                // make sure the other resolutions don't get old settings
 
835
                config->writeEntry( QString::fromLatin1( "Width" ), 0 );
 
836
                config->writeEntry( QString::fromLatin1( "Height" ), 0 );
 
837
            }
 
838
        }
 
839
        if ( !size.isEmpty() )
 
840
        {
 
841
#ifdef Q_WS_X11
 
842
            int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
 
843
                        | ( size.height() > desk.height() ? NET::MaxVert : 0 );
 
844
            if (( state & NET::Max ) == NET::Max )
 
845
                ; // no resize
 
846
            else if (( state & NET::MaxHoriz ) == NET::MaxHoriz )
 
847
                resize( width(), size.height() );
 
848
            else if (( state & NET::MaxVert ) == NET::MaxVert )
 
849
                resize( size.width(), height() );
 
850
            else
 
851
                resize( size );
 
852
            // QWidget::showMaximized() is both insufficient and broken
 
853
            KWin::setState( winId(), state );
 
854
#else
 
855
            if ( size.width() > desk.width() || size.height() > desk.height() )
 
856
                setWindowState( WindowMaximized );
 
857
            else
 
858
                resize( size );
 
859
#endif
 
860
        }
 
861
    }
 
862
 
 
863
}
 
864
#include "mergeelements.moc"