summaryrefslogtreecommitdiffstats
path: root/src/entrymerger.cpp
blob: 073d32ffdf5dd06eced077098bb355210b03ce46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/***************************************************************************
    copyright            : (C) 2007 by Robby Stephenson
    email                : [email protected]
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of version 2 of the GNU General Public License as  *
 *   published by the Free Software Foundation;                            *
 *                                                                         *
 ***************************************************************************/

#include "entrymerger.h"
#include "entry.h"
#include "collection.h"
#include "tellico_kernel.h"
#include "controller.h"
#include "progressmanager.h"
#include "statusbar.h"
#include "tellico_debug.h"

#include <klocale.h>

#include <tqtimer.h>

using Tellico::EntryMerger;

EntryMerger::EntryMerger(Data::EntryVec entries_, TQObject* parent_)
    : TQObject(parent_), m_entriesToCheck(entries_), m_origCount(entries_.count()), m_cancelled(false) {

  m_entriesLeft = m_entriesToCheck;
  Kernel::self()->beginCommandGroup(i18n("Merge Entries"));

  TQString label = i18n("Merging entries...");
  ProgressItem& item = ProgressManager::self()->newProgressItem(this, label, true /*canCancel*/);
  item.setTotalSteps(m_origCount);
  connect(&item, TQT_SIGNAL(signalCancelled(ProgressItem*)), TQT_SLOT(slotCancel()));

  // done if no entries to merge
  if(m_origCount < 2) {
    TQTimer::singleShot(500, this, TQT_SLOT(slotCleanup()));
  } else {
    slotStartNext(); // starts fetching
  }
}

void EntryMerger::slotStartNext() {
  TQString statusMsg = i18n("Total merged/scanned entries: %1/%2")
                      .tqarg(m_entriesToRemove.count())
                      .tqarg(m_origCount - m_entriesToCheck.count());
  StatusBar::self()->settqStatus(statusMsg);
  ProgressManager::self()->setProgress(this, m_origCount - m_entriesToCheck.count());

  Data::EntryPtr baseEntry = m_entriesToCheck.front();
  Data::EntryVec::Iterator it = m_entriesToCheck.begin();
  ++it; // skip checking against first
  for( ; it != m_entriesToCheck.end(); ++it) {
    bool match = cleanMerge(baseEntry, &*it);
    if(!match) {
      int score = baseEntry->collection()->sameEntry(baseEntry, &*it);
      match = score >= Data::Collection::ENTRY_PERFECT_MATCH;
    }
    if(match) {
      bool merge_ok = baseEntry->collection()->mergeEntry(baseEntry, &*it, false /*overwrite*/, true /*askUser*/);
      if(merge_ok) {
        m_entriesToRemove.append(it);
        m_entriesLeft.remove(it);
      }
    }
  }
  m_entriesToCheck.remove(baseEntry);

  if(m_cancelled || m_entriesToCheck.count() < 2) {
    TQTimer::singleShot(0, this, TQT_SLOT(slotCleanup()));
  } else {
    TQTimer::singleShot(0, this, TQT_SLOT(slotStartNext()));
  }
}

void EntryMerger::slotCancel() {
  m_cancelled = true;
}

void EntryMerger::slotCleanup() {
  Kernel::self()->removeEntries(m_entriesToRemove);
  Controller::self()->slotUpdateSelection(0, m_entriesLeft);
  StatusBar::self()->cleartqStatus();
  ProgressManager::self()->setDone(this);
  Kernel::self()->endCommandGroup();
  deleteLater();
}

bool EntryMerger::cleanMerge(Data::EntryPtr e1, Data::EntryPtr e2) const {
  // figure out if there's a clean merge possible
  Data::FieldVec fields = e1->collection()->fields();
  for(Data::FieldVecIt it = fields.begin(); it != fields.end(); ++it) {
    TQString val1 = e1->field(it);
    TQString val2 = e2->field(it);
    if(val1 != val2 && !val1.isEmpty() && !val2.isEmpty()) {
      return false;
    }
  }
  return true;
}

#include "entrymerger.moc"