summaryrefslogtreecommitdiffstats
path: root/src/translators/bibtexmlimporter.cpp
blob: 2feb2f2844c4f3264426ddc121d497e5fb7582d9 (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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/***************************************************************************
    copyright            : (C) 2003-2006 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 "bibtexmlimporter.h"
#include "tellico_xml.h"
#include "bibtexhandler.h"
#include "../collections/bibtexcollection.h"
#include "../field.h"
#include "../entry.h"
#include "../latin1literal.h"
#include "../tellico_strings.h"
#include "../progressmanager.h"
#include "../tellico_debug.h"

#include <kapplication.h>

using Tellico::Import::BibtexmlImporter;

bool BibtexmlImporter::canImport(int type) const {
  return type == Data::Collection::Bibtex;
}

Tellico::Data::CollPtr BibtexmlImporter::collection() {
  if(!m_coll) {
    loadDomDocument();
  }
  return m_coll;
}

void BibtexmlImporter::loadDomDocument() {
  QDomElement root = domDocument().documentElement();
  if(root.isNull() || root.localName() != Latin1Literal("file")) {
    setStatusMessage(i18n(errorLoad).arg(url().fileName()));
    return;
  }

  const QString& ns = XML::nsBibtexml;
  m_coll = new Data::BibtexCollection(true);

  QDomNodeList entryelems = root.elementsByTagNameNS(ns, QString::fromLatin1("entry"));
//  kdDebug() << "BibtexmlImporter::loadDomDocument - found " << entryelems.count() << " entries" << endl;

  const uint count = entryelems.count();
  const uint stepSize = QMAX(s_stepSize, count/100);
  const bool showProgress = options() & ImportProgress;

  ProgressItem& item = ProgressManager::self()->newProgressItem(this, progressLabel(), true);
  item.setTotalSteps(count);
  connect(&item, SIGNAL(signalCancelled(ProgressItem*)), SLOT(slotCancel()));
  ProgressItem::Done done(this);

  for(uint j = 0; !m_cancelled && j < entryelems.count(); ++j) {
    readEntry(entryelems.item(j));

    if(showProgress && j%stepSize == 0) {
      ProgressManager::self()->setProgress(this, j);
      kapp->processEvents();
    }
  } // end entry loop
}

void BibtexmlImporter::readEntry(const QDomNode& entryNode_) {
  QDomNode node = const_cast<QDomNode&>(entryNode_);

  Data::EntryPtr entry = new Data::Entry(m_coll);

/* The Bibtexml format looks like
  <entry id="...">
   <book>
    <authorlist>
     <author>...</author>
    </authorlist>
    <publisher>...</publisher> */

  QString type = node.firstChild().toElement().tagName();
  entry->setField(QString::fromLatin1("entry-type"), type);
  QString id = node.toElement().attribute(QString::fromLatin1("id"));
  entry->setField(QString::fromLatin1("bibtex-key"), id);

  QString name, value;
  // field values are first child of first child of entry node
  for(QDomNode n = node.firstChild().firstChild(); !n.isNull(); n = n.nextSibling()) {
    // n could be something like authorlist, with multiple authors, or just
    // a plain element with a single text child...
    // second case first
    if(n.firstChild().isText()) {
      name = n.toElement().tagName();
      value = n.toElement().text();
    } else {
      // is either titlelist, authorlist, editorlist, or keywords
      QString parName = n.toElement().tagName();
      if(parName == Latin1Literal("titlelist")) {
        for(QDomNode n2 = node.firstChild(); !n2.isNull(); n2 = n2.nextSibling()) {
          name = n2.toElement().tagName();
          value = n2.toElement().text();
          if(!name.isEmpty() && !value.isEmpty()) {
            BibtexHandler::setFieldValue(entry, name, value.simplifyWhiteSpace());
          }
        }
        name.truncate(0);
        value.truncate(0);
      } else {
        name = n.firstChild().toElement().tagName();
        if(name == Latin1Literal("keyword")) {
          name = QString::fromLatin1("keywords");
        }
        value.truncate(0);
        for(QDomNode n2 = n.firstChild(); !n2.isNull(); n2 = n2.nextSibling()) {
          // n2 could have first, middle, lastname elements...
          if(name == Latin1Literal("person")) {
            QStringList names;
            names << QString::fromLatin1("initials") << QString::fromLatin1("first")
                  << QString::fromLatin1("middle") << QString::fromLatin1("prelast")
                  << QString::fromLatin1("last") << QString::fromLatin1("lineage");
            for(QStringList::ConstIterator it = names.begin(); it != names.end(); ++it) {
              QDomNodeList list = n2.toElement().elementsByTagName(*it);
              if(list.count() > 1) {
                value += list.item(0).toElement().text();
              }
              if(*it != names.last()) {
                value += QString::fromLatin1(" ");
              }
            }
          }
          for(QDomNode n3 = n2.firstChild(); !n3.isNull(); n3 = n3.nextSibling()) {
            if(n3.isElement()) {
              value += n3.toElement().text();
            } else if(n3.isText()) {
              value += n3.toText().data();
            }
            if(n3 != n2.lastChild()) {
              value += QString::fromLatin1(" ");
            }
          }
          if(n2 != n.lastChild()) {
            value += QString::fromLatin1("; ");
          }
        }
      }
    }
    if(!name.isEmpty() && !value.isEmpty()) {
      BibtexHandler::setFieldValue(entry, name, value.simplifyWhiteSpace());
    }
  }

  m_coll->addEntries(entry);
}

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

#include "bibtexmlimporter.moc"