[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [tellico] src: Move common variant map helper function into sting_utils.cpp
From:       Robby Stephenson <null () kde ! org>
Date:       2017-04-30 21:28:27
Message-ID: E1d4wOJ-0001xq-0w () code ! kde ! org
[Download RAW message or body]

Git commit f7598af329e724270a4e491a8e5ce37eb080abff by Robby Stephenson.
Committed on 30/04/2017 at 21:25.
Pushed by rstephenson into branch 'master'.

Move common variant map helper function into sting_utils.cpp

M  +18   -46   src/fetch/allocinefetcher.cpp
M  +0    -2    src/fetch/allocinefetcher.h
M  +23   -37   src/fetch/discogsfetcher.cpp
M  +0    -2    src/fetch/discogsfetcher.h
M  +59   -87   src/fetch/doubanfetcher.cpp
M  +0    -3    src/fetch/doubanfetcher.h
M  +13   -28   src/fetch/filmasterfetcher.cpp
M  +0    -2    src/fetch/filmasterfetcher.h
M  +61   -90   src/fetch/freebasefetcher.cpp
M  +0    -2    src/fetch/freebasefetcher.h
M  +17   -32   src/fetch/googlebookfetcher.cpp
M  +0    -2    src/fetch/googlebookfetcher.h
M  +11   -25   src/fetch/ibsfetcher.cpp
M  +0    -2    src/fetch/ibsfetcher.h
M  +10   -38   src/fetch/igdbfetcher.cpp
M  +0    -2    src/fetch/igdbfetcher.h
M  +12   -26   src/fetch/moviemeterfetcher.cpp
M  +0    -2    src/fetch/moviemeterfetcher.h
M  +14   -28   src/fetch/omdbfetcher.cpp
M  +0    -2    src/fetch/omdbfetcher.h
M  +20   -36   src/fetch/openlibraryfetcher.cpp
M  +0    -2    src/fetch/openlibraryfetcher.h
M  +20   -34   src/fetch/themoviedbfetcher.cpp
M  +0    -2    src/fetch/themoviedbfetcher.h
M  +6    -22   src/fetch/vndbfetcher.cpp
M  +0    -2    src/fetch/vndbfetcher.h
M  +2    -2    src/tests/CMakeLists.txt
M  +32   -0    src/utils/string_utils.cpp
M  +7    -2    src/utils/string_utils.h

https://commits.kde.org/tellico/f7598af329e724270a4e491a8e5ce37eb080abff

diff --git a/src/fetch/allocinefetcher.cpp b/src/fetch/allocinefetcher.cpp
index 7edb710c..e1f4a5f7 100644
--- a/src/fetch/allocinefetcher.cpp
+++ b/src/fetch/allocinefetcher.cpp
@@ -318,39 +318,39 @@ Tellico::Data::CollPtr \
AbstractAllocineFetcher::createCollection() const {  
 void AbstractAllocineFetcher::populateEntry(Data::EntryPtr entry, const QVariantMap& \
resultMap) {  if(entry->collection()->hasField(QLatin1String("allocine-code"))) {
-    entry->setField(QLatin1String("allocine-code"), value(resultMap, "code"));
+    entry->setField(QLatin1String("allocine-code"), mapValue(resultMap, "code"));
   }
 
-  entry->setField(QLatin1String("title"), value(resultMap, "title"));
+  entry->setField(QLatin1String("title"), mapValue(resultMap, "title"));
   if(optionalFields().contains(QLatin1String("origtitle"))) {
-    entry->setField(QLatin1String("origtitle"), value(resultMap, "originalTitle"));
+    entry->setField(QLatin1String("origtitle"), mapValue(resultMap, \
"originalTitle"));  }
   if(entry->title().isEmpty()) {
-    entry->setField(QLatin1String("title"), value(resultMap,  "originalTitle"));
+    entry->setField(QLatin1String("title"), mapValue(resultMap,  "originalTitle"));
   }
-  entry->setField(QLatin1String("year"), value(resultMap, "productionYear"));
-  entry->setField(QLatin1String("plot"), value(resultMap, "synopsis"));
+  entry->setField(QLatin1String("year"), mapValue(resultMap, "productionYear"));
+  entry->setField(QLatin1String("plot"), mapValue(resultMap, "synopsis"));
 
-  const int runTime = value(resultMap, "runtime").toInt();
+  const int runTime = mapValue(resultMap, "runtime").toInt();
   entry->setField(QLatin1String("running-time"), QString::number(runTime/60));
 
   const QVariantList castList = \
resultMap.value(QLatin1String("castMember")).toList();  QStringList actors, \
directors, producers, composers;  foreach(const QVariant& castVariant, castList) {
     const QVariantMap castMap = castVariant.toMap();
-    const int code = value(castMap, "activity", "code").toInt();
+    const int code = mapValue(castMap, "activity", "code").toInt();
     switch(code) {
       case 8001:
-        actors << (value(castMap, "person", "name") + \
FieldFormat::columnDelimiterString() + value(castMap, "role")); +        actors << \
(mapValue(castMap, "person", "name") + FieldFormat::columnDelimiterString() + \
mapValue(castMap, "role"));  break;
       case 8002:
-        directors << value(castMap, "person", "name");
+        directors << mapValue(castMap, "person", "name");
         break;
       case 8029:
-        producers << value(castMap, "person", "name");
+        producers << mapValue(castMap, "person", "name");
         break;
       case 8003:
-        composers << value(castMap, "person", "name");
+        composers << mapValue(castMap, "person", "name");
         break;
     }
   }
@@ -360,23 +360,23 @@ void AbstractAllocineFetcher::populateEntry(Data::EntryPtr \
entry, const QVariant  entry->setField(QLatin1String("composer"), \
composers.join(FieldFormat::delimiterString()));  
   const QVariantMap releaseMap = resultMap.value(QLatin1String("release")).toMap();
-  entry->setField(QLatin1String("studio"), value(releaseMap, "distributor", \
"name")); +  entry->setField(QLatin1String("studio"), mapValue(releaseMap, \
"distributor", "name"));  
   QStringList genres;
   foreach(const QVariant& variant, resultMap.value(QLatin1String("genre")).toList()) \
                {
-    genres << i18n(value(variant.toMap(), "$").toUtf8().constData());
+    genres << i18n(mapValue(variant.toMap(), "$").toUtf8().constData());
   }
   entry->setField(QLatin1String("genre"), \
genres.join(FieldFormat::delimiterString()));  
   QStringList nats;
   foreach(const QVariant& variant, \
                resultMap.value(QLatin1String("nationality")).toList()) {
-    nats << value(variant.toMap(), "$");
+    nats << mapValue(variant.toMap(), "$");
   }
   entry->setField(QLatin1String("nationality"), \
nats.join(FieldFormat::delimiterString()));  
   QStringList langs;
   foreach(const QVariant& variant, \
                resultMap.value(QLatin1String("language")).toList()) {
-    langs << value(variant.toMap(), "$");
+    langs << mapValue(variant.toMap(), "$");
   }
   entry->setField(QLatin1String("language"), \
langs.join(FieldFormat::delimiterString()));  
@@ -385,10 +385,10 @@ void AbstractAllocineFetcher::populateEntry(Data::EntryPtr \
entry, const QVariant  entry->setField(QLatin1String("color"), i18n("Color"));
   }
 
-  entry->setField(QLatin1String("cover"), value(resultMap, "poster", "href"));
+  entry->setField(QLatin1String("cover"), mapValue(resultMap, "poster", "href"));
 
   if(optionalFields().contains(QLatin1String("allocine"))) {
-    entry->setField(QLatin1String("allocine"), value(resultMap, "link", "href"));
+    entry->setField(QLatin1String("allocine"), mapValue(resultMap, "link", "href"));
   }
 }
 
@@ -430,34 +430,6 @@ void \
AbstractAllocineFetcher::ConfigWidget::saveConfigHook(KConfigGroup& config_  \
config_.writeEntry("Max Cast", m_numCast->value());  }
 
-// static
-QString AbstractAllocineFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
-
-QString AbstractAllocineFetcher::value(const QVariantMap& map, const char* object, \
                const char* name) {
-  const QVariant v = map.value(QLatin1String(object));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::Map)) {
-    return value(v.toMap(), name);
-  } else if(v.canConvert(QVariant::List)) {
-    QVariantList list = v.toList();
-    return list.isEmpty() ? QString() : value(list.at(0).toMap(), name);
-  } else {
-    return QString();
-  }
-}
-
 QByteArray AbstractAllocineFetcher::calculateSignature(const QList<QPair<QString, \
QString> >& params_) {  typedef QPair<QString, QString> StringPair;
   QByteArray queryString;
diff --git a/src/fetch/allocinefetcher.h b/src/fetch/allocinefetcher.h
index 29470b39..e045a55a 100644
--- a/src/fetch/allocinefetcher.h
+++ b/src/fetch/allocinefetcher.h
@@ -79,8 +79,6 @@ private Q_SLOTS:
   void slotComplete(KJob* job);
 
 private:
-  static QString value(const QVariantMap& map, const char* name);
-  static QString value(const QVariantMap& map, const char* object, const char* \
name);  static QByteArray calculateSignature(const QList<QPair<QString, QString> >& \
params);  
   virtual void search() Q_DECL_OVERRIDE;
diff --git a/src/fetch/discogsfetcher.cpp b/src/fetch/discogsfetcher.cpp
index 06251cae..82286f62 100644
--- a/src/fetch/discogsfetcher.cpp
+++ b/src/fetch/discogsfetcher.cpp
@@ -273,7 +273,7 @@ void DiscogsFetcher::slotComplete(KJob* job_) {
 //  const QVariantMap resultMap = \
doc.object().toVariantMap().value(QLatin1String("feed")).toMap();  const QVariantMap \
resultMap = doc.object().toVariantMap();  
-  if(value(resultMap, "message").startsWith(QLatin1String("Invalid consumer \
token"))) { +  if(mapValue(resultMap, "message").startsWith(QLatin1String("Invalid \
consumer token"))) {  message(i18n("The Discogs.com server reports a token error."),
             MessageHandler::Error);
     stop();
@@ -301,25 +301,25 @@ void DiscogsFetcher::slotComplete(KJob* job_) {
 }
 
 void DiscogsFetcher::populateEntry(Data::EntryPtr entry_, const QVariantMap& \
                resultMap_, bool fullData_) {
-  entry_->setField(QLatin1String("discogs-id"), value(resultMap_, "id"));
-  entry_->setField(QLatin1String("title"), value(resultMap_, "title"));
-  entry_->setField(QLatin1String("year"),  value(resultMap_, "year"));
-  entry_->setField(QLatin1String("genre"),  value(resultMap_, "genres"));
+  entry_->setField(QLatin1String("discogs-id"), mapValue(resultMap_, "id"));
+  entry_->setField(QLatin1String("title"), mapValue(resultMap_, "title"));
+  entry_->setField(QLatin1String("year"),  mapValue(resultMap_, "year"));
+  entry_->setField(QLatin1String("genre"),  mapValue(resultMap_, "genres"));
 
   QStringList artists;
   foreach(const QVariant& artist, \
                resultMap_.value(QLatin1String("artists")).toList()) {
-    artists << value(artist.toMap(), "name");
+    artists << mapValue(artist.toMap(), "name");
   }
   entry_->setField(QLatin1String("artist"), \
artists.join(FieldFormat::delimiterString()));  
   QStringList labels;
   foreach(const QVariant& label, resultMap_.value(QLatin1String("labels")).toList()) \
                {
-    labels << value(label.toMap(), "name");
+    labels << mapValue(label.toMap(), "name");
   }
   entry_->setField(QLatin1String("label"), \
labels.join(FieldFormat::delimiterString()));  
   /* thumb value is not always in the full data, so go ahead and set it now */
-  QString coverUrl = value(resultMap_, "thumb");
+  QString coverUrl = mapValue(resultMap_, "thumb");
   if(!coverUrl.isEmpty()) {
     entry_->setField(QLatin1String("cover"), coverUrl);
   }
@@ -333,14 +333,14 @@ void DiscogsFetcher::populateEntry(Data::EntryPtr entry_, const \
QVariantMap& res  // if there is a CD, prefer that in the track list
   bool hasCD = false;
   foreach(const QVariant& format, \
                resultMap_.value(QLatin1String("formats")).toList()) {
-    if(value(format.toMap(), "name") == QLatin1String("CD")) {
+    if(mapValue(format.toMap(), "name") == QLatin1String("CD")) {
       entry_->setField(QLatin1String("medium"), i18n("Compact Disc"));
       hasCD = true;
-    } else if(value(format.toMap(), "name") == QLatin1String("Vinyl")) {
+    } else if(mapValue(format.toMap(), "name") == QLatin1String("Vinyl")) {
       entry_->setField(QLatin1String("medium"), i18n("Vinyl"));
-    } else if(value(format.toMap(), "name") == QLatin1String("Cassette")) {
+    } else if(mapValue(format.toMap(), "name") == QLatin1String("Cassette")) {
       entry_->setField(QLatin1String("medium"), i18n("Cassette"));
-    } else if(!hasCD && value(format.toMap(), "name") == QLatin1String("DVD")) {
+    } else if(!hasCD && mapValue(format.toMap(), "name") == QLatin1String("DVD")) {
       // sometimes a CD and DVD both are included. If we're using the CD, ignore the \
DVD  entry_->setField(QLatin1String("medium"), i18n("DVD"));
     }
@@ -349,52 +349,52 @@ void DiscogsFetcher::populateEntry(Data::EntryPtr entry_, const \
QVariantMap& res  QStringList tracks;
   foreach(const QVariant& track, \
resultMap_.value(QLatin1String("tracklist")).toList()) {  const QVariantMap trackMap \
                = track.toMap();
-    if(value(trackMap, "type_") != QLatin1String("track")) {
+    if(mapValue(trackMap, "type_") != QLatin1String("track")) {
       continue;
     }
 
     // Releases might include a CD and a DVD, for example
     // prefer only the tracks on the CD. Allow positionns of just numbers
-    if(hasCD && !(value(trackMap, "position").at(0).isNumber() || 
-                  value(trackMap, "position").startsWith(QLatin1String("CD")))) {
+    if(hasCD && !(mapValue(trackMap, "position").at(0).isNumber() ||
+                  mapValue(trackMap, "position").startsWith(QLatin1String("CD")))) {
       continue;
     }
 
     QStringList trackInfo;
-    trackInfo << value(trackMap, "title");
+    trackInfo << mapValue(trackMap, "title");
     if(trackMap.contains(QLatin1String("artists"))) {
       QStringList artists;
       foreach(const QVariant& artist, \
                trackMap.value(QLatin1String("artists")).toList()) {
-        artists << value(artist.toMap(), "name");
+        artists << mapValue(artist.toMap(), "name");
       }
       trackInfo << artists.join(FieldFormat::delimiterString());
     } else {
       trackInfo << entry_->field(QLatin1String("artist"));
     }
-    trackInfo << value(trackMap, "duration");
+    trackInfo << mapValue(trackMap, "duration");
     tracks << trackInfo.join(FieldFormat::columnDelimiterString());
   }
   entry_->setField(QLatin1String("track"), \
tracks.join(FieldFormat::rowDelimiterString()));  
   if(entry_->collection()->hasField(QLatin1String("discogs"))) {
-    entry_->setField(QLatin1String("discogs"), value(resultMap_, "uri"));
+    entry_->setField(QLatin1String("discogs"), mapValue(resultMap_, "uri"));
   }
 
   if(entry_->collection()->hasField(QLatin1String("nationality"))) {
-    entry_->setField(QLatin1String("nationality"), value(resultMap_, "country"));
+    entry_->setField(QLatin1String("nationality"), mapValue(resultMap_, "country"));
   }
 
   if(entry_->collection()->hasField(QLatin1String("producer"))) {
     QStringList producers;
     foreach(const QVariant& extraartist, \
                resultMap_.value(QLatin1String("extraartists")).toList()) {
-      if(value(extraartist.toMap(), "role").contains(QLatin1String("Producer"))) {
-        producers << value(extraartist.toMap(), "name");
+      if(mapValue(extraartist.toMap(), "role").contains(QLatin1String("Producer"))) \
{ +        producers << mapValue(extraartist.toMap(), "name");
       }
     }
     entry_->setField(QLatin1String("producer"), \
producers.join(FieldFormat::delimiterString()));  }
 
-  entry_->setField(QLatin1String("comments"),  value(resultMap_, "notes"));
+  entry_->setField(QLatin1String("comments"),  mapValue(resultMap_, "notes"));
 }
 
 Tellico::Fetch::ConfigWidget* DiscogsFetcher::configWidget(QWidget* parent_) const {
@@ -465,17 +465,3 @@ void DiscogsFetcher::ConfigWidget::saveConfigHook(KConfigGroup& \
config_) {  QString DiscogsFetcher::ConfigWidget::preferredName() const {
   return DiscogsFetcher::defaultName();
 }
-
-// static
-QString DiscogsFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/discogsfetcher.h b/src/fetch/discogsfetcher.h
index add6ff15..d17d6902 100644
--- a/src/fetch/discogsfetcher.h
+++ b/src/fetch/discogsfetcher.h
@@ -97,8 +97,6 @@ private:
   virtual FetchRequest updateRequest(Data::EntryPtr entry) Q_DECL_OVERRIDE;
   void populateEntry(Data::EntryPtr entry, const QVariantMap& resultMap, bool \
fullData);  
-  static QString value(const QVariantMap& map, const char* name);
-
   bool m_started;
 
   QString m_apiKey;
diff --git a/src/fetch/doubanfetcher.cpp b/src/fetch/doubanfetcher.cpp
index e5f9fc73..95cb892d 100644
--- a/src/fetch/doubanfetcher.cpp
+++ b/src/fetch/doubanfetcher.cpp
@@ -178,13 +178,13 @@ void DoubanFetcher::slotCompleteISBN(KJob* job_) {
   const QVariantMap resultMap = doc.object().toVariantMap();
 
   // code == 6000 for no result
-  if(value(resultMap, "code") == QLatin1String("6000")) {
-    message(value(resultMap, "msg"), MessageHandler::Error);
+  if(mapValue(resultMap, "code") == QLatin1String("6000")) {
+    message(mapValue(resultMap, "msg"), MessageHandler::Error);
   } else {
     Data::EntryPtr entry = createEntry(resultMap);
     FetchResult* r = new FetchResult(Fetcher::Ptr(this), entry);
     m_entries.insert(r->uid, entry);
-    m_matches.insert(r->uid, QUrl(value(resultMap, "url")));
+    m_matches.insert(r->uid, QUrl(mapValue(resultMap, "url")));
     emit signalResultFound(r);
   }
 
@@ -229,11 +229,11 @@ void DoubanFetcher::slotComplete(KJob* job_) {
     case Data::Collection::Bibtex:
       foreach(const QVariant& v, resultsMap.value(QLatin1String("books")).toList()) \
{  const QVariantMap resultMap = v.toMap();
-        FetchResult* r = new FetchResult(Fetcher::Ptr(this), value(resultMap, \
                "title"),
-                                         value(resultMap, "author") + \
                QLatin1Char('/') +
-                                         value(resultMap, "publisher") + \
                QLatin1Char('/') +
-                                         value(resultMap, "pubdate").left(4));
-        m_matches.insert(r->uid, QUrl(value(resultMap, "url")));
+        FetchResult* r = new FetchResult(Fetcher::Ptr(this), mapValue(resultMap, \
"title"), +                                         mapValue(resultMap, "author") + \
QLatin1Char('/') + +                                         mapValue(resultMap, \
"publisher") + QLatin1Char('/') + +                                         \
mapValue(resultMap, "pubdate").left(4)); +        m_matches.insert(r->uid, \
QUrl(mapValue(resultMap, "url")));  emit signalResultFound(r);
       }
       break;
@@ -241,13 +241,13 @@ void DoubanFetcher::slotComplete(KJob* job_) {
     case Data::Collection::Video:
       foreach(const QVariant& v, \
resultsMap.value(QLatin1String("subjects")).toList()) {  const QVariantMap resultMap \
                = v.toMap();
-        FetchResult* r = new FetchResult(Fetcher::Ptr(this), value(resultMap, \
                "title"),
-                                         value(resultMap, "directors", "name") + \
                QLatin1Char('/') +
-                                         value(resultMap, "year"));
+        FetchResult* r = new FetchResult(Fetcher::Ptr(this), mapValue(resultMap, \
"title"), +                                         mapValue(resultMap, "directors", \
"name") + QLatin1Char('/') + +                                         \
mapValue(resultMap, "year"));  // movie results don't appear to have a url field
         m_matches.insert(r->uid, QUrl(QLatin1String(DOUBAN_API_URL) +
                                       QLatin1String("movie/subject/") +
-                                      value(resultMap, "id")));
+                                      mapValue(resultMap, "id")));
         emit signalResultFound(r);
       }
       break;
@@ -255,14 +255,14 @@ void DoubanFetcher::slotComplete(KJob* job_) {
     case Data::Collection::Album:
       foreach(const QVariant& v, resultsMap.value(QLatin1String("musics")).toList()) \
{  const QVariantMap resultMap = v.toMap();
-        FetchResult* r = new FetchResult(Fetcher::Ptr(this), value(resultMap, \
                "title"),
-                                         value(resultMap, "attrs", "singer") + \
                QLatin1Char('/') +
-                                         value(resultMap, "attrs", "publisher") + \
                QLatin1Char('/') +
-                                         value(resultMap, "attrs", \
"pubdate").left(4)); +        FetchResult* r = new FetchResult(Fetcher::Ptr(this), \
mapValue(resultMap, "title"), +                                         \
mapValue(resultMap, "attrs", "singer") + QLatin1Char('/') + +                         \
mapValue(resultMap, "attrs", "publisher") + QLatin1Char('/') + +                      \
mapValue(resultMap, "attrs", "pubdate").left(4));  // movie results don't appear to \
have a url field  m_matches.insert(r->uid, QUrl(QLatin1String(DOUBAN_API_URL) +
                                       QLatin1String("music/") +
-                                      value(resultMap, "id")));
+                                      mapValue(resultMap, "id")));
         emit signalResultFound(r);
       }
       break;
@@ -310,14 +310,14 @@ Tellico::Data::EntryPtr DoubanFetcher::createEntry(const \
QVariantMap& resultMap_  case Data::Collection::Bibtex:
       coll = new Data::BookCollection(true);
       if(optionalFields().contains(QLatin1String("origtitle")) &&
-        !value(resultMap_, "origin_title").isEmpty() &&
+        !mapValue(resultMap_, "origin_title").isEmpty() &&
         !coll->hasField(QLatin1String("origtitle"))) {
         Data::FieldPtr f(new Data::Field(QLatin1String("origtitle"), i18n("Original \
Title")));  f->setFormatType(FieldFormat::FormatTitle);
         coll->addField(f);
       }
       if(optionalFields().contains(QLatin1String("douban")) &&
-        !value(resultMap_, "alt").isEmpty() &&
+        !mapValue(resultMap_, "alt").isEmpty() &&
         !coll->hasField(QLatin1String("douban"))) {
         Data::FieldPtr f(new Data::Field(QLatin1String("douban"), i18n("Douban \
Link"), Data::Field::URL));  f->setCategory(i18n("General"));
@@ -329,14 +329,14 @@ Tellico::Data::EntryPtr DoubanFetcher::createEntry(const \
QVariantMap& resultMap_  case Data::Collection::Video:
       coll = new Data::VideoCollection(true);
       if(optionalFields().contains(QLatin1String("origtitle")) &&
-        !value(resultMap_, "original_title").isEmpty() &&
+        !mapValue(resultMap_, "original_title").isEmpty() &&
         !coll->hasField(QLatin1String("origtitle"))) {
         Data::FieldPtr f(new Data::Field(QLatin1String("origtitle"), i18n("Original \
Title")));  f->setFormatType(FieldFormat::FormatTitle);
         coll->addField(f);
       }
       if(optionalFields().contains(QLatin1String("douban")) &&
-        !value(resultMap_, "alt").isEmpty() &&
+        !mapValue(resultMap_, "alt").isEmpty() &&
         !coll->hasField(QLatin1String("douban"))) {
         Data::FieldPtr f(new Data::Field(QLatin1String("douban"), i18n("Douban \
Link"), Data::Field::URL));  f->setCategory(i18n("General"));
@@ -348,14 +348,14 @@ Tellico::Data::EntryPtr DoubanFetcher::createEntry(const \
QVariantMap& resultMap_  case Data::Collection::Album:
       coll = new Data::MusicCollection(true);
       if(optionalFields().contains(QLatin1String("origtitle")) &&
-        !value(resultMap_, "original_title").isEmpty() &&
+        !mapValue(resultMap_, "original_title").isEmpty() &&
         !coll->hasField(QLatin1String("origtitle"))) {
         Data::FieldPtr f(new Data::Field(QLatin1String("origtitle"), i18n("Original \
Title")));  f->setFormatType(FieldFormat::FormatTitle);
         coll->addField(f);
       }
       if(optionalFields().contains(QLatin1String("douban")) &&
-        !value(resultMap_, "alt").isEmpty() &&
+        !mapValue(resultMap_, "alt").isEmpty() &&
         !coll->hasField(QLatin1String("douban"))) {
         Data::FieldPtr f(new Data::Field(QLatin1String("douban"), i18n("Douban \
Link"), Data::Field::URL));  f->setCategory(i18n("General"));
@@ -372,43 +372,43 @@ Tellico::Data::EntryPtr DoubanFetcher::createEntry(const \
QVariantMap& resultMap_  }
 
 void DoubanFetcher::populateBookEntry(Data::EntryPtr entry, const QVariantMap& \
                resultMap_) {
-  entry->setField(QLatin1String("title"), value(resultMap_, "title"));
-  entry->setField(QLatin1String("subtitle"), value(resultMap_, "subtitle"));
-  entry->setField(QLatin1String("author"), value(resultMap_, "author"));
-  entry->setField(QLatin1String("translator"), value(resultMap_, "translator"));
-  entry->setField(QLatin1String("publisher"), value(resultMap_, "publisher"));
+  entry->setField(QLatin1String("title"), mapValue(resultMap_, "title"));
+  entry->setField(QLatin1String("subtitle"), mapValue(resultMap_, "subtitle"));
+  entry->setField(QLatin1String("author"), mapValue(resultMap_, "author"));
+  entry->setField(QLatin1String("translator"), mapValue(resultMap_, "translator"));
+  entry->setField(QLatin1String("publisher"), mapValue(resultMap_, "publisher"));
 
-  const QString binding = value(resultMap_, "binding");
+  const QString binding = mapValue(resultMap_, "binding");
   if(binding == QString::fromUtf8("精装")) {
     entry->setField(QLatin1String("binding"), i18n("Hardback"));
   } else if(binding == QString::fromUtf8("平装")) {
     entry->setField(QLatin1String("binding"), i18n("Paperback"));
   }
 
-  entry->setField(QLatin1String("pub_year"), value(resultMap_, "pubdate").left(4));
-  entry->setField(QLatin1String("isbn"), value(resultMap_, "isbn10"));
-  entry->setField(QLatin1String("pages"), value(resultMap_, "pages"));
-  entry->setField(QLatin1String("cover"), value(resultMap_, "image"));
-  entry->setField(QLatin1String("keyword"), value(resultMap_, "tags", "title"));
+  entry->setField(QLatin1String("pub_year"), mapValue(resultMap_, \
"pubdate").left(4)); +  entry->setField(QLatin1String("isbn"), mapValue(resultMap_, \
"isbn10")); +  entry->setField(QLatin1String("pages"), mapValue(resultMap_, \
"pages")); +  entry->setField(QLatin1String("cover"), mapValue(resultMap_, "image"));
+  entry->setField(QLatin1String("keyword"), mapValue(resultMap_, "tags", "title"));
 
   if(optionalFields().contains(QLatin1String("origtitle")) &&
-     !value(resultMap_, "origin_title").isEmpty()) {
-    entry->setField(QLatin1String("origtitle"), value(resultMap_, "origin_title"));
+     !mapValue(resultMap_, "origin_title").isEmpty()) {
+    entry->setField(QLatin1String("origtitle"), mapValue(resultMap_, \
"origin_title"));  }
   if(optionalFields().contains(QLatin1String("douban"))) {
-    entry->setField(QLatin1String("douban"), value(resultMap_, "alt"));
+    entry->setField(QLatin1String("douban"), mapValue(resultMap_, "alt"));
   }
-  entry->setField(QLatin1String("plot"), value(resultMap_, "summary"));
+  entry->setField(QLatin1String("plot"), mapValue(resultMap_, "summary"));
 }
 
 void DoubanFetcher::populateVideoEntry(Data::EntryPtr entry, const QVariantMap& \
                resultMap_) {
-  entry->setField(QLatin1String("title"), value(resultMap_, "title"));
-  entry->setField(QLatin1String("genre"), value(resultMap_, "genres"));
-  entry->setField(QLatin1String("director"), value(resultMap_, "directors", \
                "name"));
-  entry->setField(QLatin1String("writer"), value(resultMap_, "writers", "name"));
-  entry->setField(QLatin1String("year"), value(resultMap_, "year"));
-  entry->setField(QLatin1String("cover"), value(resultMap_, "images", "medium"));
-  entry->setField(QLatin1String("plot"), value(resultMap_, "summary"));
+  entry->setField(QLatin1String("title"), mapValue(resultMap_, "title"));
+  entry->setField(QLatin1String("genre"), mapValue(resultMap_, "genres"));
+  entry->setField(QLatin1String("director"), mapValue(resultMap_, "directors", \
"name")); +  entry->setField(QLatin1String("writer"), mapValue(resultMap_, "writers", \
"name")); +  entry->setField(QLatin1String("year"), mapValue(resultMap_, "year"));
+  entry->setField(QLatin1String("cover"), mapValue(resultMap_, "images", "medium"));
+  entry->setField(QLatin1String("plot"), mapValue(resultMap_, "summary"));
 
   QStringList actors;
   foreach(const QVariant& v, resultMap_.value(QLatin1String("casts")).toList()) {
@@ -417,23 +417,23 @@ void DoubanFetcher::populateVideoEntry(Data::EntryPtr entry, \
const QVariantMap&  entry->setField(QLatin1String("cast"), \
actors.join(FieldFormat::rowDelimiterString()));  
   if(optionalFields().contains(QLatin1String("origtitle")) &&
-     !value(resultMap_, "original_title").isEmpty()) {
-    entry->setField(QLatin1String("origtitle"), value(resultMap_, \
"original_title")); +     !mapValue(resultMap_, "original_title").isEmpty()) {
+    entry->setField(QLatin1String("origtitle"), mapValue(resultMap_, \
"original_title"));  }
   if(optionalFields().contains(QLatin1String("douban"))) {
-    entry->setField(QLatin1String("douban"), value(resultMap_, "alt"));
+    entry->setField(QLatin1String("douban"), mapValue(resultMap_, "alt"));
   }
 }
 
 void DoubanFetcher::populateMusicEntry(Data::EntryPtr entry, const QVariantMap& \
                resultMap_) {
-  entry->setField(QLatin1String("title"), value(resultMap_, "title"));
-  entry->setField(QLatin1String("cover"), value(resultMap_, "image"));
-  entry->setField(QLatin1String("artist"), value(resultMap_, "attrs", "singer"));
-  entry->setField(QLatin1String("label"), value(resultMap_, "attrs", "publisher"));
-  entry->setField(QLatin1String("year"), value(resultMap_, "attrs", \
                "pubdate").left(4));
-
-  if(value(resultMap_, "attrs", "media") == QLatin1String("Audio CD") ||
-     value(resultMap_, "attrs", "media") == QLatin1String("CD")) {
+  entry->setField(QLatin1String("title"), mapValue(resultMap_, "title"));
+  entry->setField(QLatin1String("cover"), mapValue(resultMap_, "image"));
+  entry->setField(QLatin1String("artist"), mapValue(resultMap_, "attrs", "singer"));
+  entry->setField(QLatin1String("label"), mapValue(resultMap_, "attrs", \
"publisher")); +  entry->setField(QLatin1String("year"), mapValue(resultMap_, \
"attrs", "pubdate").left(4)); +
+  if(mapValue(resultMap_, "attrs", "media") == QLatin1String("Audio CD") ||
+     mapValue(resultMap_, "attrs", "media") == QLatin1String("CD")) {
     entry->setField(QLatin1String("medium"), i18n("Compact Disc"));
   }
 
@@ -470,11 +470,11 @@ void DoubanFetcher::populateMusicEntry(Data::EntryPtr entry, \
const QVariantMap&  entry->setField(QLatin1String("track"), \
tracks.join(FieldFormat::rowDelimiterString()));  
   if(optionalFields().contains(QLatin1String("origtitle")) &&
-     !value(resultMap_, "original_title").isEmpty()) {
-    entry->setField(QLatin1String("origtitle"), value(resultMap_, \
"original_title")); +     !mapValue(resultMap_, "original_title").isEmpty()) {
+    entry->setField(QLatin1String("origtitle"), mapValue(resultMap_, \
"original_title"));  }
   if(optionalFields().contains(QLatin1String("douban"))) {
-    entry->setField(QLatin1String("douban"), value(resultMap_, "alt"));
+    entry->setField(QLatin1String("douban"), mapValue(resultMap_, "alt"));
   }
 }
 
@@ -527,31 +527,3 @@ void DoubanFetcher::ConfigWidget::saveConfigHook(KConfigGroup& \
config_) {  QString DoubanFetcher::ConfigWidget::preferredName() const {
   return DoubanFetcher::defaultName();
 }
-
-// static
-QString DoubanFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
-
-QString DoubanFetcher::value(const QVariantMap& map, const char* object, const char* \
                name) {
-  const QVariant v = map.value(QLatin1String(object));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::Map)) {
-    return value(v.toMap(), name);
-  } else if(v.canConvert(QVariant::List)) {
-    QVariantList list = v.toList();
-    return list.isEmpty() ? QString() : value(list.at(0).toMap(), name);
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/doubanfetcher.h b/src/fetch/doubanfetcher.h
index 476775c0..0d45538f 100644
--- a/src/fetch/doubanfetcher.h
+++ b/src/fetch/doubanfetcher.h
@@ -95,9 +95,6 @@ private:
   void populateVideoEntry(Data::EntryPtr entry, const QVariantMap& resultMap);
   void populateMusicEntry(Data::EntryPtr entry, const QVariantMap& resultMap);
 
-  static QString value(const QVariantMap& map, const char* name);
-  static QString value(const QVariantMap& map, const char* object, const char* \
                name);
-
   bool m_started;
 
   QHash<int, QUrl> m_matches;
diff --git a/src/fetch/filmasterfetcher.cpp b/src/fetch/filmasterfetcher.cpp
index 9b8115a9..1146e817 100644
--- a/src/fetch/filmasterfetcher.cpp
+++ b/src/fetch/filmasterfetcher.cpp
@@ -193,8 +193,8 @@ void FilmasterFetcher::slotComplete(KJob* job_) {
         QStringList uris;
         foreach(const QVariant& person, personList) {
           const QVariantMap personMap = person.toMap();
-          uris << value(personMap, "films_played_uri");
-          uris << value(personMap, "films_directed_uri");
+          uris << mapValue(personMap, "films_played_uri");
+          uris << mapValue(personMap, "films_directed_uri");
         }
         foreach(const QString& uri, uris) {
           QUrl u(QString::fromLatin1(FILMASTER_API_URL));
@@ -244,23 +244,23 @@ void FilmasterFetcher::slotComplete(KJob* job_) {
 }
 
 void FilmasterFetcher::populateEntry(Data::EntryPtr entry_, const QVariantMap& \
                result_) {
-  entry_->setField(QLatin1String("title"), value(result_, "title"));
-  entry_->setField(QLatin1String("year"), value(result_, "release_year"));
-  entry_->setField(QLatin1String("genre"), value(result_, "tags"));
-  entry_->setField(QLatin1String("nationality"), value(result_, \
                "production_country_list"));
-  entry_->setField(QLatin1String("cover"), value(result_, "image"));
-  entry_->setField(QLatin1String("plot"), value(result_, "description"));
+  entry_->setField(QLatin1String("title"), mapValue(result_, "title"));
+  entry_->setField(QLatin1String("year"), mapValue(result_, "release_year"));
+  entry_->setField(QLatin1String("genre"), mapValue(result_, "tags"));
+  entry_->setField(QLatin1String("nationality"), mapValue(result_, \
"production_country_list")); +  entry_->setField(QLatin1String("cover"), \
mapValue(result_, "image")); +  entry_->setField(QLatin1String("plot"), \
mapValue(result_, "description"));  
   QStringList directors;
   foreach(const QVariant& director, \
result_.value(QLatin1String("directors")).toList()) {  const QVariantMap directorMap \
                = director.toMap();
-    directors << value(directorMap, "name") + QLatin1Char(' ') + value(directorMap, \
"surname"); +    directors << mapValue(directorMap, "name") + QLatin1Char(' ') + \
mapValue(directorMap, "surname");  }
   if(!directors.isEmpty()) {
     entry_->setField(QLatin1String("director"), \
directors.join(FieldFormat::delimiterString()));  }
 
-  const QString castUri = value(result_, "characters_uri");
+  const QString castUri = mapValue(result_, "characters_uri");
   if(!castUri.isEmpty()) {
     QUrl u(QString::fromLatin1(FILMASTER_API_URL));
     u.setPath(castUri);
@@ -271,9 +271,9 @@ void FilmasterFetcher::populateEntry(Data::EntryPtr entry_, const \
QVariantMap& r  foreach(const QVariant& castResult, castList) {
       const QVariantMap castMap = castResult.toMap();
       const QVariantMap nameMap = castMap.value(QLatin1String("person")).toMap();
-      castLines << value(nameMap, "name") + QLatin1Char(' ') + value(nameMap, \
"surname") +      castLines << mapValue(nameMap, "name") + QLatin1Char(' ') + \
mapValue(nameMap, "surname")  + FieldFormat::columnDelimiterString()
-                 + value(castMap, "character");
+                 + mapValue(castMap, "character");
     }
     if(!castLines.isEmpty()) {
       entry_->setField(QLatin1String("cast"), \
castLines.join(FieldFormat::rowDelimiterString())); @@ -281,7 +281,7 @@ void \
FilmasterFetcher::populateEntry(Data::EntryPtr entry_, const QVariantMap& r  }
 
   if(optionalFields().contains(QLatin1String("filmaster"))) {
-    entry_->setField(QLatin1String("filmaster"), \
QLatin1String("http://filmaster.com/film/") + value(result_, "permalink")); +    \
entry_->setField(QLatin1String("filmaster"), \
QLatin1String("http://filmaster.com/film/") + mapValue(result_, "permalink"));  }
 }
 
@@ -319,18 +319,3 @@ void \
FilmasterFetcher::ConfigWidget::saveConfigHook(KConfigGroup&) {  QString \
FilmasterFetcher::ConfigWidget::preferredName() const {  return \
FilmasterFetcher::defaultName();  }
-
-QString FilmasterFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else if(v.canConvert(QVariant::Map)) {
-    return v.toMap().value(QLatin1String("value")).toString();
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/filmasterfetcher.h b/src/fetch/filmasterfetcher.h
index 5a560bd5..23209538 100644
--- a/src/fetch/filmasterfetcher.h
+++ b/src/fetch/filmasterfetcher.h
@@ -87,8 +87,6 @@ private Q_SLOTS:
   void slotComplete(KJob* job);
 
 private:
-  static QString value(const QVariantMap& map, const char* name);
-
   virtual void search() Q_DECL_OVERRIDE;
   virtual FetchRequest updateRequest(Data::EntryPtr entry) Q_DECL_OVERRIDE;
 
diff --git a/src/fetch/freebasefetcher.cpp b/src/fetch/freebasefetcher.cpp
index 42c29dbc..6bc31f9d 100644
--- a/src/fetch/freebasefetcher.cpp
+++ b/src/fetch/freebasefetcher.cpp
@@ -282,7 +282,7 @@ Tellico::Data::EntryPtr FreebaseFetcher::fetchEntryHook(uint \
                uid_) {
               .value(QLatin1String("/common/document/text")).toMap();
         const QVariantList valueList = \
articleMap.value(QLatin1String("values")).toList();  if(!valueList.isEmpty()) {
-          entry->setField(article_field, value(valueList.first().toMap(), "value"));
+          entry->setField(article_field, mapValue(valueList.first().toMap(), \
"value"));  }
       }
     }
@@ -361,7 +361,7 @@ void FreebaseFetcher::slotComplete(KJob* job_) {
     }
   } else if(responseMap.contains(QLatin1String("error"))) {
     // we have an error!!!!!!!!!!!!!
-    const QString msg = value(responseMap, "error", "message");
+    const QString msg = mapValue(responseMap, "error", "message");
     if(!msg.isEmpty()) {
       myDebug() << "message:" << msg;
       message(msg, MessageHandler::Error);
@@ -389,46 +389,46 @@ void FreebaseFetcher::slotComplete(KJob* job_) {
     QVariantMap resultMap = result.toMap();
 
     Data::EntryPtr entry(new Data::Entry(coll));
-    entry->setField(QLatin1String("title"), value(resultMap, "name"));
+    entry->setField(QLatin1String("title"), mapValue(resultMap, "name"));
     if(optionalFields().contains(QLatin1String("freebase"))) {
-      entry->setField(QLatin1String("freebase"), QLatin1String(FREEBASE_VIEW_URL) + \
value(resultMap, "id")); +      entry->setField(QLatin1String("freebase"), \
QLatin1String(FREEBASE_VIEW_URL) + mapValue(resultMap, "id"));  }
 
     switch(type) {
       case Data::Collection::Book:
       case Data::Collection::Bibtex:
-        entry->setField(QLatin1String("pub_year"),  value(resultMap, \
"publication_date").left(4)); +        entry->setField(QLatin1String("pub_year"),  \
mapValue(resultMap, "publication_date").left(4));  {
-          QString isbn = value(resultMap, "isbn", "isbn");
+          QString isbn = mapValue(resultMap, "isbn", "isbn");
           if(isbn.isEmpty()) {
-            isbn = value(resultMap, "/media_common/cataloged_instance/isbn13", \
"value"); +            isbn = mapValue(resultMap, \
"/media_common/cataloged_instance/isbn13", "value");  }
           entry->setField(QLatin1String("isbn"), isbn);
         }
-        entry->setField(QLatin1String("publisher"), value(resultMap, "publisher"));
-        entry->setField(QLatin1String("pages"),     value(resultMap, \
"number_of_pages")); +        entry->setField(QLatin1String("publisher"), \
mapValue(resultMap, "publisher")); +        entry->setField(QLatin1String("pages"),   \
mapValue(resultMap, "number_of_pages"));  {
-          QString lccn = value(resultMap, "LCCN");
+          QString lccn = mapValue(resultMap, "LCCN");
           if(lccn.isEmpty()) {
-            lccn = value(resultMap, "/media_common/cataloged_instance/lccn", \
"value"); +            lccn = mapValue(resultMap, \
"/media_common/cataloged_instance/lccn", "value");  }
           entry->setField(QLatin1String("lccn"), lccn);
         }
-        entry->setField(QLatin1String("author"),    value(resultMap, "work:book", \
                "author"));
-        entry->setField(QLatin1String("editor"),    value(resultMap, "work:book", \
                "editor"));
-        entry->setField(QLatin1String("cr_year"),   value(resultMap, "work:book", \
"copyright_date").left(4)); +        entry->setField(QLatin1String("author"),    \
mapValue(resultMap, "work:book", "author")); +        \
entry->setField(QLatin1String("editor"),    mapValue(resultMap, "work:book", \
"editor")); +        entry->setField(QLatin1String("cr_year"),   mapValue(resultMap, \
"work:book", "copyright_date").left(4));  {
-          const QString series = value(resultMap, "work:book", "part_of_series");
+          const QString series = mapValue(resultMap, "work:book", "part_of_series");
           // some have duplicate values?
           QStringList seriesList = FieldFormat::splitValue(series);
           seriesList.removeDuplicates();
           entry->setField(QLatin1String("series"), \
seriesList.join(FieldFormat::delimiterString()));  }
-        entry->setField(QLatin1String("language"),  value(resultMap, "work:book", \
                "original_language"));
-        entry->setField(QLatin1String("pages"),     value(resultMap, \
                "number_of_pages", "numbered_pages"));
-        entry->setField(QLatin1String("genre"), \
FieldFormat::capitalize(value(resultMap, "book", "genre"))); +        \
entry->setField(QLatin1String("language"),  mapValue(resultMap, "work:book", \
"original_language")); +        entry->setField(QLatin1String("pages"),     \
mapValue(resultMap, "number_of_pages", "numbered_pages")); +        \
entry->setField(QLatin1String("genre"), FieldFormat::capitalize(mapValue(resultMap, \
"book", "genre")));  {
-          QString binding = value(resultMap, "binding");
+          QString binding = mapValue(resultMap, "binding");
           if(!binding.isEmpty()) {
             if(binding.toLower() == QLatin1String("hardcover")) {
               binding = i18n("Hardback");
@@ -443,27 +443,27 @@ void FreebaseFetcher::slotComplete(KJob* job_) {
         break;
 
       case Data::Collection::ComicBook:
-        entry->setField(QLatin1String("writer"),     value(resultMap, "editor"));
-        entry->setField(QLatin1String("issue"),      value(resultMap, \
                "issue_number"));
-        entry->setField(QLatin1String("pub_year"),   value(resultMap, \
                "date_of_publication").left(4));
-        entry->setField(QLatin1String("publisher"),  value(resultMap, \
                "!/comic_books/comic_book_series/issues", "publisher"));
-        entry->setField(QLatin1String("series"),     value(resultMap, \
                "!/comic_books/comic_book_series/issues", "name"));
-        entry->setField(QLatin1String("genre"),      value(resultMap, \
"!/comic_books/comic_book_series/issues", "genre")); +        \
entry->setField(QLatin1String("writer"),     mapValue(resultMap, "editor")); +        \
entry->setField(QLatin1String("issue"),      mapValue(resultMap, "issue_number")); +  \
entry->setField(QLatin1String("pub_year"),   mapValue(resultMap, \
"date_of_publication").left(4)); +        entry->setField(QLatin1String("publisher"), \
mapValue(resultMap, "!/comic_books/comic_book_series/issues", "publisher")); +        \
entry->setField(QLatin1String("series"),     mapValue(resultMap, \
"!/comic_books/comic_book_series/issues", "name")); +        \
entry->setField(QLatin1String("genre"),      mapValue(resultMap, \
"!/comic_books/comic_book_series/issues", "genre"));  {
           QStringList artists;
-          QString colors = value(resultMap, "cover_colors");
+          QString colors = mapValue(resultMap, "cover_colors");
           if(!colors.isEmpty()) {
             artists << colors;
           }
-          QString inks = value(resultMap, "cover_inks");
+          QString inks = mapValue(resultMap, "cover_inks");
           if(!inks.isEmpty())  {
             artists << inks;
           }
-          QString letters = value(resultMap, "cover_letters");
+          QString letters = mapValue(resultMap, "cover_letters");
           if(!letters.isEmpty()) {
             artists << letters;
           }
-          QString pencils = value(resultMap, "cover_pencils");
+          QString pencils = mapValue(resultMap, "cover_pencils");
           if(!pencils.isEmpty()) {
             artists << pencils;
           }
@@ -473,23 +473,23 @@ void FreebaseFetcher::slotComplete(KJob* job_) {
 
       case Data::Collection::Video:
         {
-          entry->setField(QLatin1String("director"),      value(resultMap, \
                "directed_by"));
-          entry->setField(QLatin1String("producer"),      value(resultMap, \
                "produced_by"));
-          entry->setField(QLatin1String("writer"),        value(resultMap, \
                "written_by"));
-          entry->setField(QLatin1String("composer"),      value(resultMap, \
                "music"));
-          QString studio = value(resultMap, "production_companies");
+          entry->setField(QLatin1String("director"),      mapValue(resultMap, \
"directed_by")); +          entry->setField(QLatin1String("producer"),      \
mapValue(resultMap, "produced_by")); +          \
entry->setField(QLatin1String("writer"),        mapValue(resultMap, "written_by")); + \
entry->setField(QLatin1String("composer"),      mapValue(resultMap, "music")); +      \
QString studio = mapValue(resultMap, "production_companies");  if(studio.isEmpty()) {
-            studio = value(resultMap, "distributors", "distributor");
+            studio = mapValue(resultMap, "distributors", "distributor");
           }
           entry->setField(QLatin1String("studio"),        studio);
-          entry->setField(QLatin1String("genre"),         value(resultMap, \
                "genre"));
-          entry->setField(QLatin1String("nationality"),   value(resultMap, \
                "country"));
-          entry->setField(QLatin1String("keyword"),       value(resultMap, \
"subjects")); +          entry->setField(QLatin1String("genre"),         \
mapValue(resultMap, "genre")); +          \
entry->setField(QLatin1String("nationality"),   mapValue(resultMap, "country")); +    \
entry->setField(QLatin1String("keyword"),       mapValue(resultMap, "subjects"));  // \
                sometimes the rating comes back with multiple values
-          const QStringList certs = FieldFormat::splitValue(value(resultMap, \
"rating")); +          const QStringList certs = \
                FieldFormat::splitValue(mapValue(resultMap, "rating"));
           entry->setField(QLatin1String("certification"), certs.isEmpty() ? \
                QString() : certs.first());
-          entry->setField(QLatin1String("year"),          value(resultMap, \
                "initial_release_date").left(4));
-          entry->setField(QLatin1String("running-time"),  value(resultMap, \
"runtime", "runtime")); +          entry->setField(QLatin1String("year"),          \
mapValue(resultMap, "initial_release_date").left(4)); +          \
entry->setField(QLatin1String("running-time"),  mapValue(resultMap, "runtime", \
"runtime"));  
           QStringList castList;
           const QVariantList castResult = \
resultMap.value(QLatin1String("starring")).toList(); @@ -513,13 +513,13 @@ void \
FreebaseFetcher::slotComplete(KJob* job_) {  
       case Data::Collection::Album:
         {
-          entry->setField(QLatin1String("artist"), value(resultMap, "artist"));
+          entry->setField(QLatin1String("artist"), mapValue(resultMap, "artist"));
           if(entry->field(QLatin1String("artist")).isEmpty()) {
-            entry->setField(QLatin1String("artist"), value(resultMap, \
"credited_as")); +            entry->setField(QLatin1String("artist"), \
mapValue(resultMap, "credited_as"));  }
-          entry->setField(QLatin1String("year"),   value(resultMap, \
                "release_date").left(4));
-          entry->setField(QLatin1String("label"),  value(resultMap, "label"));
-          entry->setField(QLatin1String("genre"),  value(resultMap, "album", \
"genre")); +          entry->setField(QLatin1String("year"),   mapValue(resultMap, \
"release_date").left(4)); +          entry->setField(QLatin1String("label"),  \
mapValue(resultMap, "label")); +          entry->setField(QLatin1String("genre"),  \
mapValue(resultMap, "album", "genre"));  
           QStringList trackList;
           const QVariantList trackResult = \
resultMap.value(QLatin1String("track")).toList(); @@ -546,11 +546,11 @@ void \
FreebaseFetcher::slotComplete(KJob* job_) {  case Data::Collection::Game:
         {
           // video game stuff
-          entry->setField(QLatin1String("genre"),     value(resultMap, \
                "cvg_genre"));
-          entry->setField(QLatin1String("developer"), value(resultMap, \
                "developer"));
-          entry->setField(QLatin1String("publisher"), value(resultMap, \
                "publisher"));
-          entry->setField(QLatin1String("year"),      value(resultMap, \
                "release_date").left(4));
-          const QStringList platforms = FieldFormat::splitValue(value(resultMap, \
"platforms")); +          entry->setField(QLatin1String("genre"),     \
mapValue(resultMap, "cvg_genre")); +          \
entry->setField(QLatin1String("developer"), mapValue(resultMap, "developer")); +      \
entry->setField(QLatin1String("publisher"), mapValue(resultMap, "publisher")); +      \
entry->setField(QLatin1String("year"),      mapValue(resultMap, \
"release_date").left(4)); +          const QStringList platforms = \
FieldFormat::splitValue(mapValue(resultMap, "platforms"));  if(!platforms.isEmpty()) \
{  // just grab first one
             entry->setField(QLatin1String("platform"), \
i18n(platforms.at(0).toUtf8().constData())); @@ -561,12 +561,12 @@ void \
FreebaseFetcher::slotComplete(KJob* job_) {  case Data::Collection::BoardGame:
         {
           // video game stuff
-          entry->setField(QLatin1String("genre"),     value(resultMap, "genre"));
-          entry->setField(QLatin1String("designer"),  value(resultMap, "designer"));
-          entry->setField(QLatin1String("publisher"), value(resultMap, \
                "publisher"));
-          entry->setField(QLatin1String("year"),      value(resultMap, \
                "introduced").left(4));
-          const int minPlayers = value(resultMap, "number_of_players", \
                "low_value").toInt();
-          const int maxPlayers = value(resultMap, "number_of_players", \
"high_value").toInt(); +          entry->setField(QLatin1String("genre"),     \
mapValue(resultMap, "genre")); +          entry->setField(QLatin1String("designer"),  \
mapValue(resultMap, "designer")); +          \
entry->setField(QLatin1String("publisher"), mapValue(resultMap, "publisher")); +      \
entry->setField(QLatin1String("year"),      mapValue(resultMap, \
"introduced").left(4)); +          const int minPlayers = mapValue(resultMap, \
"number_of_players", "low_value").toInt(); +          const int maxPlayers = \
mapValue(resultMap, "number_of_players", "high_value").toInt();  if(minPlayers > 0 && \
maxPlayers > 0) {  QStringList players;
             for(int i = minPlayers; i <= maxPlayers; ++i) {
@@ -582,19 +582,19 @@ void FreebaseFetcher::slotComplete(KJob* job_) {
     }
 
     // set the image and article ids. The actual content gets loaded in \
                fetchEntryHook()
-    entry->setField(QLatin1String("cover"), value(resultMap, "/common/topic/image", \
"id")); +    entry->setField(QLatin1String("cover"), mapValue(resultMap, \
                "/common/topic/image", "id"));
     if(type == Data::Collection::Album && \
entry->field(QLatin1String("cover")).isEmpty()) {  // musical releases can have the \
                image from the album
       QVariantList albumList = resultMap.value(QLatin1String("album")).toList();
       if(!albumList.isEmpty()) {
         QVariantMap albumMap = albumList.at(0).toMap();
-        entry->setField(QLatin1String("cover"), value(albumMap, \
"/common/topic/image", "id")); +        entry->setField(QLatin1String("cover"), \
mapValue(albumMap, "/common/topic/image", "id"));  }
     }
     if(type == Data::Collection::Video) {
-      entry->setField(QLatin1String("plot"), value(resultMap, \
"/common/topic/article", "id")); +      entry->setField(QLatin1String("plot"), \
                mapValue(resultMap, "/common/topic/article", "id"));
     } else if(type == Data::Collection::Game || type == Data::Collection::BoardGame) \
                {
-      entry->setField(QLatin1String("description"), value(resultMap, \
"/common/topic/article", "id")); +      entry->setField(QLatin1String("description"), \
mapValue(resultMap, "/common/topic/article", "id"));  }
 
     FetchResult* r = new FetchResult(Fetcher::Ptr(this), entry);
@@ -992,35 +992,6 @@ QString FreebaseFetcher::ConfigWidget::preferredName() const {
   return FreebaseFetcher::defaultName();
 }
 
-QString FreebaseFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else if(v.canConvert(QVariant::Map)) {
-    return v.toMap().value(QLatin1String("name")).toString();
-  } else {
-    return QString();
-  }
-}
-
-QString FreebaseFetcher::value(const QVariantMap& map, const char* object, const \
                char* name) {
-  const QVariant v = map.value(QLatin1String(object));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::Map)) {
-    return value(v.toMap(), name);
-  } else if(v.canConvert(QVariant::List)) {
-    QVariantList list = v.toList();
-    return list.isEmpty() ? QString() : value(list.at(0).toMap(), name);
-  } else {
-    return QString();
-  }
-}
-
 QByteArray FreebaseFetcher::serialize(const QVariant& value_) {
   return QJsonDocument::fromVariant(value_).toJson(QJsonDocument::Compact);
 }
diff --git a/src/fetch/freebasefetcher.h b/src/fetch/freebasefetcher.h
index a888179e..cc0c0a3a 100644
--- a/src/fetch/freebasefetcher.h
+++ b/src/fetch/freebasefetcher.h
@@ -93,8 +93,6 @@ private Q_SLOTS:
   void slotComplete(KJob* job);
 
 private:
-  static QString value(const QVariantMap& map, const char* name);
-  static QString value(const QVariantMap& map, const char* object, const char* \
name);  static QByteArray serialize(const QVariant& value);
 
   virtual void search() Q_DECL_OVERRIDE;
diff --git a/src/fetch/googlebookfetcher.cpp b/src/fetch/googlebookfetcher.cpp
index 8db8ac62..1e972304 100644
--- a/src/fetch/googlebookfetcher.cpp
+++ b/src/fetch/googlebookfetcher.cpp
@@ -288,24 +288,24 @@ void GoogleBookFetcher::slotComplete(KJob* job_) {
 
 void GoogleBookFetcher::populateEntry(Data::EntryPtr entry, const QVariantMap& \
resultMap) {  if(entry->collection()->hasField(QLatin1String("gbs-link"))) {
-    entry->setField(QLatin1String("gbs-link"), value(resultMap, "selfLink"));
+    entry->setField(QLatin1String("gbs-link"), mapValue(resultMap, "selfLink"));
   }
 
   const QVariantMap volumeMap = \
                resultMap.value(QLatin1String("volumeInfo")).toMap();
-  entry->setField(QLatin1String("title"),     value(volumeMap, "title"));
-  entry->setField(QLatin1String("subtitle"),  value(volumeMap, "subtitle"));
-  entry->setField(QLatin1String("pub_year"),  value(volumeMap, \
                "publishedDate").left(4));
-  entry->setField(QLatin1String("author"),    value(volumeMap, "authors"));
+  entry->setField(QLatin1String("title"),     mapValue(volumeMap, "title"));
+  entry->setField(QLatin1String("subtitle"),  mapValue(volumeMap, "subtitle"));
+  entry->setField(QLatin1String("pub_year"),  mapValue(volumeMap, \
"publishedDate").left(4)); +  entry->setField(QLatin1String("author"),    \
mapValue(volumeMap, "authors"));  // workaround for bug, where publisher can be \
                enclosed in quotes
-  QString pub = value(volumeMap, "publisher");
+  QString pub = mapValue(volumeMap, "publisher");
   if(pub.startsWith(QLatin1Char('"')) && pub.endsWith(QLatin1Char('"'))) {
     pub.chop(1);
     pub = pub.remove(0, 1);
   }
   entry->setField(QLatin1String("publisher"), pub);
-  entry->setField(QLatin1String("pages"),     value(volumeMap, "pageCount"));
-  entry->setField(QLatin1String("language"),  value(volumeMap, "language"));
-  entry->setField(QLatin1String("comments"),  value(volumeMap, "description"));
+  entry->setField(QLatin1String("pages"),     mapValue(volumeMap, "pageCount"));
+  entry->setField(QLatin1String("language"),  mapValue(volumeMap, "language"));
+  entry->setField(QLatin1String("comments"),  mapValue(volumeMap, "description"));
 
   QStringList catList = volumeMap.value(QLatin1String("categories")).toStringList();
   // google is going to give us a lot of categories
@@ -322,11 +322,11 @@ void GoogleBookFetcher::populateEntry(Data::EntryPtr entry, \
const QVariantMap& r  QString isbn;
   foreach(const QVariant& idVariant, \
volumeMap.value(QLatin1String("industryIdentifiers")).toList()) {  const QVariantMap \
                idMap = idVariant.toMap();
-    if(value(idMap, "type") == QLatin1String("ISBN_10")) {
-      isbn = value(idMap, "identifier");
+    if(mapValue(idMap, "type") == QLatin1String("ISBN_10")) {
+      isbn = mapValue(idMap, "identifier");
       break;
-    } else if(value(idMap, "type") == QLatin1String("ISBN_13")) {
-      isbn = value(idMap, "identifier");
+    } else if(mapValue(idMap, "type") == QLatin1String("ISBN_13")) {
+      isbn = mapValue(idMap, "identifier");
       // allow isbn10 to override, so don't break here
     }
   }
@@ -338,15 +338,15 @@ void GoogleBookFetcher::populateEntry(Data::EntryPtr entry, \
const QVariantMap& r  
   const QVariantMap imageMap = volumeMap.value(QLatin1String("imageLinks")).toMap();
   if(imageMap.contains(QLatin1String("small"))) {
-    entry->setField(QLatin1String("cover"), value(imageMap, "small"));
+    entry->setField(QLatin1String("cover"), mapValue(imageMap, "small"));
   } else if(imageMap.contains(QLatin1String("thumbnail"))) {
-    entry->setField(QLatin1String("cover"), value(imageMap, "thumbnail"));
+    entry->setField(QLatin1String("cover"), mapValue(imageMap, "thumbnail"));
   } else if(imageMap.contains(QLatin1String("smallThumbnail"))) {
-    entry->setField(QLatin1String("cover"), value(imageMap, "smallThumbnail"));
+    entry->setField(QLatin1String("cover"), mapValue(imageMap, "smallThumbnail"));
   }
 
   if(optionalFields().contains(QLatin1String("googlebook"))) {
-    entry->setField(QLatin1String("googlebook"), value(volumeMap, "infoLink"));
+    entry->setField(QLatin1String("googlebook"), mapValue(volumeMap, "infoLink"));
   }
 }
 
@@ -421,18 +421,3 @@ void \
GoogleBookFetcher::ConfigWidget::saveConfigHook(KConfigGroup& config_) {  QString \
GoogleBookFetcher::ConfigWidget::preferredName() const {  return \
GoogleBookFetcher::defaultName();  }
-
-// static
-QString GoogleBookFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
-
diff --git a/src/fetch/googlebookfetcher.h b/src/fetch/googlebookfetcher.h
index 437c3833..e413ec60 100644
--- a/src/fetch/googlebookfetcher.h
+++ b/src/fetch/googlebookfetcher.h
@@ -100,8 +100,6 @@ private:
   void endJob(KIO::StoredTransferJob* job);
   void populateEntry(Data::EntryPtr entry, const QVariantMap& resultMap);
 
-  static QString value(const QVariantMap& map, const char* name);
-
   QHash<int, Data::EntryPtr> m_entries;
   QList< QPointer<KIO::StoredTransferJob> > m_jobs;
 
diff --git a/src/fetch/ibsfetcher.cpp b/src/fetch/ibsfetcher.cpp
index b14fb5d8..62d6d7fe 100644
--- a/src/fetch/ibsfetcher.cpp
+++ b/src/fetch/ibsfetcher.cpp
@@ -250,15 +250,15 @@ Tellico::Data::EntryPtr IBSFetcher::parseEntry(const QString& \
str_) {  Data::EntryPtr entry(new Data::Entry(coll));
 
   // as genre, take the last breadcrumb
-  QString genre = value(objectMap, "breadcrumb");
+  QString genre = mapValue(objectMap, "breadcrumb");
   genre = genre.section(QLatin1String(">"), -1);
   entry->setField(QLatin1String("genre"), genre);
 
   // the title in the embedded loses it's identifier? "La..."
-  entry->setField(QLatin1String("title"), value(resultMap, "name"));
-  entry->setField(QLatin1String("author"), value(resultMap, "author"));
+  entry->setField(QLatin1String("title"), mapValue(resultMap, "name"));
+  entry->setField(QLatin1String("author"), mapValue(resultMap, "author"));
 
-  const QString bookFormat = value(resultMap, "bookFormat");
+  const QString bookFormat = mapValue(resultMap, "bookFormat");
   if(bookFormat == QLatin1String("http://schema.org/Paperback")) {
     entry->setField(QLatin1String("binding"), i18n("Paperback"));
   } else if(bookFormat == QLatin1String("http://schema.org/Hardcover")) {
@@ -267,17 +267,17 @@ Tellico::Data::EntryPtr IBSFetcher::parseEntry(const QString& \
str_) {  entry->setField(QLatin1String("binding"), i18n("E-Book"));
   }
 
-  entry->setField(QLatin1String("pub_year"), value(resultMap, "datePublished"));
-  entry->setField(QLatin1String("cover"), value(resultMap, "image"));
-  entry->setField(QLatin1String("isbn"), value(resultMap, "isbn"));
+  entry->setField(QLatin1String("pub_year"), mapValue(resultMap, "datePublished"));
+  entry->setField(QLatin1String("cover"), mapValue(resultMap, "image"));
+  entry->setField(QLatin1String("isbn"), mapValue(resultMap, "isbn"));
 
   // inLanguage is upper-case language code
-  const QString lang = value(resultMap, "inLanguage");
+  const QString lang = mapValue(resultMap, "inLanguage");
   entry->setField(QLatin1String("language"), \
QLocale(lang.toLower()).nativeLanguageName());  
-  entry->setField(QLatin1String("plot"), value(resultMap, "description"));
-  entry->setField(QLatin1String("pages"), value(resultMap, "numberOfPages"));
-  entry->setField(QLatin1String("publisher"), value(resultMap, "publisher"));
+  entry->setField(QLatin1String("plot"), mapValue(resultMap, "description"));
+  entry->setField(QLatin1String("pages"), mapValue(resultMap, "numberOfPages"));
+  entry->setField(QLatin1String("publisher"), mapValue(resultMap, "publisher"));
 
   // multiple authors do not show up in the embedded JSON
   QRegExp titleDivRx(QLatin1String("<div id=\"title\">(.*)</div>"));
@@ -354,17 +354,3 @@ IBSFetcher::ConfigWidget::ConfigWidget(QWidget* parent_)
 QString IBSFetcher::ConfigWidget::preferredName() const {
   return IBSFetcher::defaultName();
 }
-
-// static
-QString IBSFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/ibsfetcher.h b/src/fetch/ibsfetcher.h
index 8bfb6041..97e1945a 100644
--- a/src/fetch/ibsfetcher.h
+++ b/src/fetch/ibsfetcher.h
@@ -82,8 +82,6 @@ private:
   virtual FetchRequest updateRequest(Data::EntryPtr entry) Q_DECL_OVERRIDE;
   Data::EntryPtr parseEntry(const QString& str);
 
-  static QString value(const QVariantMap& map, const char* name);
-
   int m_total;
   QHash<int, Data::EntryPtr> m_entries;
   QHash<int, QUrl> m_matches;
diff --git a/src/fetch/igdbfetcher.cpp b/src/fetch/igdbfetcher.cpp
index 7fbce943..4fa1516d 100644
--- a/src/fetch/igdbfetcher.cpp
+++ b/src/fetch/igdbfetcher.cpp
@@ -252,13 +252,13 @@ void IGDBFetcher::slotComplete(KJob* job_) {
 }
 
 void IGDBFetcher::populateEntry(Data::EntryPtr entry_, const QVariantMap& \
                resultMap_) {
-  entry_->setField(QLatin1String("title"), value(resultMap_, "name"));
-  entry_->setField(QLatin1String("description"), value(resultMap_, "summary"));
-  entry_->setField(QLatin1String("certification"), \
                m_esrbHash.value(value(resultMap_, "esrb", "rating")));
-  entry_->setField(QLatin1String("pub-id"), value(resultMap_, "publishers"));
-  entry_->setField(QLatin1String("dev-id"), value(resultMap_, "developers"));
+  entry_->setField(QLatin1String("title"), mapValue(resultMap_, "name"));
+  entry_->setField(QLatin1String("description"), mapValue(resultMap_, "summary"));
+  entry_->setField(QLatin1String("certification"), \
m_esrbHash.value(mapValue(resultMap_, "esrb", "rating"))); +  \
entry_->setField(QLatin1String("pub-id"), mapValue(resultMap_, "publishers")); +  \
entry_->setField(QLatin1String("dev-id"), mapValue(resultMap_, "developers"));  
-  QString cover = value(resultMap_, "cover", "url");
+  QString cover = mapValue(resultMap_, "cover", "url");
   if(cover.startsWith(QLatin1Char('/'))) {
     cover.prepend(QLatin1String("https:"));
   }
@@ -278,7 +278,7 @@ void IGDBFetcher::populateEntry(Data::EntryPtr entry_, const \
QVariantMap& result  if(!releases.isEmpty()) {
     QVariantMap releaseMap = releases.at(0).toMap();
     // for now just grab the year of the first release
-    entry_->setField(QLatin1String("year"), value(releaseMap, "y"));
+    entry_->setField(QLatin1String("year"), mapValue(releaseMap, "y"));
     const QString platform = \
                m_platformHash.value(releaseMap.value(QLatin1String("platform")).toInt());
                
     if(platform == QLatin1String("Nintendo Entertainment System (NES)")) {
       entry_->setField(QLatin1String("platform"), i18n("Nintendo"));
@@ -312,11 +312,11 @@ void IGDBFetcher::populateEntry(Data::EntryPtr entry_, const \
QVariantMap& result  }
 
   if(optionalFields().contains(QLatin1String("pegi"))) {
-    entry_->setField(QLatin1String("pegi"), m_pegiHash.value(value(resultMap_, \
"pegi", "rating"))); +    entry_->setField(QLatin1String("pegi"), \
m_pegiHash.value(mapValue(resultMap_, "pegi", "rating")));  }
 
   if(optionalFields().contains(QLatin1String("igdb"))) {
-    entry_->setField(QLatin1String("igdb"), value(resultMap_, "url"));
+    entry_->setField(QLatin1String("igdb"), mapValue(resultMap_, "url"));
   }
 }
 
@@ -354,7 +354,7 @@ QString IGDBFetcher::companyName(const QString& companyId_) const \
{  #endif
 
   QJsonDocument doc = QJsonDocument::fromJson(data);
-  const QString company = value(doc.array().toVariantList().at(0).toMap(), "name");
+  const QString company = mapValue(doc.array().toVariantList().at(0).toMap(), \
"name");  m_companyHash.insert(companyId_, company);
   return company;
 }
@@ -607,34 +607,6 @@ QString IGDBFetcher::ConfigWidget::preferredName() const {
   return IGDBFetcher::defaultName();
 }
 
-// static
-QString IGDBFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
-
-QString IGDBFetcher::value(const QVariantMap& map, const char* object, const char* \
                name) {
-  const QVariant v = map.value(QLatin1String(object));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::Map)) {
-    return value(v.toMap(), name);
-  } else if(v.canConvert(QVariant::List)) {
-    QVariantList list = v.toList();
-    return list.isEmpty() ? QString() : value(list.at(0).toMap(), name);
-  } else {
-    return QString();
-  }
-}
-
 QPointer<KIO::StoredTransferJob> IGDBFetcher::igdbJob(const QUrl& url_, const \
QString& apiKey_) {  QPointer<KIO::StoredTransferJob> job = KIO::storedGet(url_, \
KIO::NoReload, KIO::HideProgressInfo);  \
job->addMetaData(QLatin1String("customHTTPHeader"), QLatin1String("X-Mashape-Key: ") \
                + apiKey_);
diff --git a/src/fetch/igdbfetcher.h b/src/fetch/igdbfetcher.h
index dd8ea3c4..6052bd2e 100644
--- a/src/fetch/igdbfetcher.h
+++ b/src/fetch/igdbfetcher.h
@@ -92,8 +92,6 @@ private:
   void populateHashes();
   QString companyName(const QString& companyId) const;
 
-  static QString value(const QVariantMap& map, const char* name);
-  static QString value(const QVariantMap& map, const char* object, const char* \
name);  static QPointer<KIO::StoredTransferJob> igdbJob(const QUrl& url, const \
QString& apiKey);  
   bool m_started;
diff --git a/src/fetch/moviemeterfetcher.cpp b/src/fetch/moviemeterfetcher.cpp
index b3559319..ae634977 100644
--- a/src/fetch/moviemeterfetcher.cpp
+++ b/src/fetch/moviemeterfetcher.cpp
@@ -244,36 +244,36 @@ void MovieMeterFetcher::slotComplete(KJob* job_) {
 }
 
 void MovieMeterFetcher::populateEntry(Data::EntryPtr entry_, const QVariantMap& \
                resultMap_, bool fullData_) {
-  entry_->setField(QLatin1String("moviemeter-id"), value(resultMap_, "id"));
-  entry_->setField(QLatin1String("title"), value(resultMap_, "title"));
-  entry_->setField(QLatin1String("year"),  value(resultMap_, "year"));
+  entry_->setField(QLatin1String("moviemeter-id"), mapValue(resultMap_, "id"));
+  entry_->setField(QLatin1String("title"), mapValue(resultMap_, "title"));
+  entry_->setField(QLatin1String("year"),  mapValue(resultMap_, "year"));
 
   // if we only need cursory data, then we're done
   if(!fullData_) {
     return;
   }
 
-  entry_->setField(QLatin1String("genre"),  value(resultMap_, "genres"));
-  entry_->setField(QLatin1String("plot"),  value(resultMap_, "plot"));
-  entry_->setField(QLatin1String("running-time"),  value(resultMap_, "duration"));
-  entry_->setField(QLatin1String("director"),  value(resultMap_, "directors"));
-  entry_->setField(QLatin1String("nationality"),  value(resultMap_, "countries"));
+  entry_->setField(QLatin1String("genre"),  mapValue(resultMap_, "genres"));
+  entry_->setField(QLatin1String("plot"),  mapValue(resultMap_, "plot"));
+  entry_->setField(QLatin1String("running-time"),  mapValue(resultMap_, \
"duration")); +  entry_->setField(QLatin1String("director"),  mapValue(resultMap_, \
"directors")); +  entry_->setField(QLatin1String("nationality"),  \
mapValue(resultMap_, "countries"));  
   QStringList castList;
   foreach(const QVariant& actor, resultMap_.value(QLatin1String("actors")).toList()) \
                {
-    castList << value(actor.toMap(), "name");
+    castList << mapValue(actor.toMap(), "name");
   }
   entry_->setField(QLatin1String("cast"), \
castList.join(FieldFormat::rowDelimiterString()));  
   if(entry_->collection()->hasField(QLatin1String("moviemeter"))) {
-    entry_->setField(QLatin1String("moviemeter"), value(resultMap_, "url"));
+    entry_->setField(QLatin1String("moviemeter"), mapValue(resultMap_, "url"));
   }
 
   if(entry_->collection()->hasField(QLatin1String("alttitle"))) {
-    entry_->setField(QLatin1String("alttitle"), value(resultMap_, \
"alternative_title")); +    entry_->setField(QLatin1String("alttitle"), \
mapValue(resultMap_, "alternative_title"));  }
 
-  entry_->setField(QLatin1String("cover"), \
value(resultMap_.value(QLatin1String("posters")).toMap(), "small")); +  \
entry_->setField(QLatin1String("cover"), \
mapValue(resultMap_.value(QLatin1String("posters")).toMap(), "small"));  }
 
 Tellico::Fetch::ConfigWidget* MovieMeterFetcher::configWidget(QWidget* parent_) \
const { @@ -311,17 +311,3 @@ void \
MovieMeterFetcher::ConfigWidget::saveConfigHook(KConfigGroup&) {  QString \
MovieMeterFetcher::ConfigWidget::preferredName() const {  return \
MovieMeterFetcher::defaultName();  }
-
-// static
-QString MovieMeterFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/moviemeterfetcher.h b/src/fetch/moviemeterfetcher.h
index 13faf168..f28b8ab7 100644
--- a/src/fetch/moviemeterfetcher.h
+++ b/src/fetch/moviemeterfetcher.h
@@ -90,8 +90,6 @@ private:
   virtual FetchRequest updateRequest(Data::EntryPtr entry) Q_DECL_OVERRIDE;
   void populateEntry(Data::EntryPtr entry, const QVariantMap& resultMap, bool \
fullData);  
-  static QString value(const QVariantMap& map, const char* name);
-
   bool m_started;
 
   QHash<int, Data::EntryPtr> m_entries;
diff --git a/src/fetch/omdbfetcher.cpp b/src/fetch/omdbfetcher.cpp
index 246980f3..3f65a816 100644
--- a/src/fetch/omdbfetcher.cpp
+++ b/src/fetch/omdbfetcher.cpp
@@ -260,15 +260,15 @@ void OMDBFetcher::slotComplete(KJob* job_) {
 }
 
 void OMDBFetcher::populateEntry(Data::EntryPtr entry_, const QVariantMap& \
                resultMap_, bool fullData_) {
-  entry_->setField(QLatin1String("imdb-id"), value(resultMap_, "imdbID"));
-  entry_->setField(QLatin1String("title"), value(resultMap_, "Title"));
-  entry_->setField(QLatin1String("year"),  value(resultMap_, "Year"));
+  entry_->setField(QLatin1String("imdb-id"), mapValue(resultMap_, "imdbID"));
+  entry_->setField(QLatin1String("title"), mapValue(resultMap_, "Title"));
+  entry_->setField(QLatin1String("year"),  mapValue(resultMap_, "Year"));
 
   if(!fullData_) {
     return;
   }
 
-  const QString cert = value(resultMap_, "Rated");
+  const QString cert = mapValue(resultMap_, "Rated");
   Data::FieldPtr certField = \
entry_->collection()->fieldByName(QLatin1String("certification"));  if(certField) {
     foreach(const QString& value, certField->allowed()) {
@@ -278,35 +278,35 @@ void OMDBFetcher::populateEntry(Data::EntryPtr entry_, const \
QVariantMap& result  }
     }
   }
-  entry_->setField(QLatin1String("running-time"), value(resultMap_, "Runtime")
+  entry_->setField(QLatin1String("running-time"), mapValue(resultMap_, "Runtime")
                                                   \
.remove(QRegExp(QLatin1String("[^\\d]"))));  
-  const QStringList genres = value(resultMap_, "Genre").split(QLatin1String(", "));
+  const QStringList genres = mapValue(resultMap_, "Genre").split(QLatin1String(", \
"));  entry_->setField(QLatin1String("genre"), \
genres.join(FieldFormat::delimiterString()));  
-  const QStringList directors = value(resultMap_, "Director").split(QLatin1String(", \
")); +  const QStringList directors = mapValue(resultMap_, \
"Director").split(QLatin1String(", "));  entry_->setField(QLatin1String("director"), \
directors.join(FieldFormat::delimiterString()));  
-  QStringList writers = value(resultMap_, "Writer").split(QLatin1String(", "));
+  QStringList writers = mapValue(resultMap_, "Writer").split(QLatin1String(", "));
   // some wrtiers have parentheticals, remove those
   entry_->setField(QLatin1String("writer"), writers
                                            \
                .replaceInStrings(QRegExp(QLatin1String("\\s*\\(.+\\)\\s*")), \
                QString())
                                            .join(FieldFormat::delimiterString()));
 
-  const QStringList producers = value(resultMap_, "Producer").split(QLatin1String(", \
")); +  const QStringList producers = mapValue(resultMap_, \
"Producer").split(QLatin1String(", "));  entry_->setField(QLatin1String("producer"), \
producers.join(FieldFormat::delimiterString()));  
-  const QStringList actors = value(resultMap_, "Actors").split(QLatin1String(", "));
+  const QStringList actors = mapValue(resultMap_, "Actors").split(QLatin1String(", \
"));  entry_->setField(QLatin1String("cast"), \
actors.join(FieldFormat::rowDelimiterString()));  
-  const QStringList countries = value(resultMap_, "Country").split(QLatin1String(", \
")); +  const QStringList countries = mapValue(resultMap_, \
"Country").split(QLatin1String(", "));  \
entry_->setField(QLatin1String("nationality"), \
countries.join(FieldFormat::delimiterString()));  
-  const QStringList langs = value(resultMap_, "Language").split(QLatin1String(", \
")); +  const QStringList langs = mapValue(resultMap_, \
"Language").split(QLatin1String(", "));  entry_->setField(QLatin1String("language"), \
langs.join(FieldFormat::delimiterString()));  
-  entry_->setField(QLatin1String("cover"), value(resultMap_, "Poster"));
-  entry_->setField(QLatin1String("plot"), value(resultMap_, "Plot"));
+  entry_->setField(QLatin1String("cover"), mapValue(resultMap_, "Poster"));
+  entry_->setField(QLatin1String("plot"), mapValue(resultMap_, "Plot"));
 
   if(optionalFields().contains(QLatin1String("imdb"))) {
     if(!entry_->collection()->hasField(QLatin1String("imdb"))) {
@@ -355,17 +355,3 @@ void OMDBFetcher::ConfigWidget::saveConfigHook(KConfigGroup&) {
 QString OMDBFetcher::ConfigWidget::preferredName() const {
   return OMDBFetcher::defaultName();
 }
-
-// static
-QString OMDBFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/omdbfetcher.h b/src/fetch/omdbfetcher.h
index 48483e31..74eace21 100644
--- a/src/fetch/omdbfetcher.h
+++ b/src/fetch/omdbfetcher.h
@@ -99,8 +99,6 @@ private:
   virtual FetchRequest updateRequest(Data::EntryPtr entry) Q_DECL_OVERRIDE;
   void populateEntry(Data::EntryPtr entry, const QVariantMap& resultMap, bool \
fullData);  
-  static QString value(const QVariantMap& map, const char* name);
-
   bool m_started;
 
   QHash<int, Data::EntryPtr> m_entries;
diff --git a/src/fetch/openlibraryfetcher.cpp b/src/fetch/openlibraryfetcher.cpp
index fb392f1b..165c683f 100644
--- a/src/fetch/openlibraryfetcher.cpp
+++ b/src/fetch/openlibraryfetcher.cpp
@@ -263,23 +263,23 @@ void OpenLibraryFetcher::slotComplete(KJob* job_) {
 
     Data::EntryPtr entry(new Data::Entry(coll));
 
-    entry->setField(QLatin1String("title"), value(resultMap, "title"));
-    entry->setField(QLatin1String("subtitle"), value(resultMap, "subtitle"));
-    entry->setField(QLatin1String("pub_year"), value(resultMap, "publish_date"));
-    QString isbn = value(resultMap, "isbn_10");
+    entry->setField(QLatin1String("title"), mapValue(resultMap, "title"));
+    entry->setField(QLatin1String("subtitle"), mapValue(resultMap, "subtitle"));
+    entry->setField(QLatin1String("pub_year"), mapValue(resultMap, "publish_date"));
+    QString isbn = mapValue(resultMap, "isbn_10");
     if(isbn.isEmpty()) {
-      isbn = value(resultMap, "isbn_13");
+      isbn = mapValue(resultMap, "isbn_13");
     }
     if(!isbn.isEmpty()) {
       ISBNValidator val(this);
       val.fixup(isbn);
       entry->setField(QLatin1String("isbn"), isbn);
     }
-    entry->setField(QLatin1String("lccn"), value(resultMap, "lccn"));
-    entry->setField(QLatin1String("genre"), value(resultMap, "genres"));
-    entry->setField(QLatin1String("keyword"), value(resultMap, "subjects"));
-    entry->setField(QLatin1String("edition"), value(resultMap, "edition_name"));
-    QString binding = value(resultMap, "physical_format");
+    entry->setField(QLatin1String("lccn"), mapValue(resultMap, "lccn"));
+    entry->setField(QLatin1String("genre"), mapValue(resultMap, "genres"));
+    entry->setField(QLatin1String("keyword"), mapValue(resultMap, "subjects"));
+    entry->setField(QLatin1String("edition"), mapValue(resultMap, "edition_name"));
+    QString binding = mapValue(resultMap, "physical_format");
     if(binding.toLower() == QLatin1String("hardcover")) {
       binding = QLatin1String("Hardback");
     } else if(binding.toLower().contains(QLatin1String("paperback"))) {
@@ -288,18 +288,18 @@ void OpenLibraryFetcher::slotComplete(KJob* job_) {
     if(!binding.isEmpty()) {
       entry->setField(QLatin1String("binding"), i18n(binding.toUtf8().constData()));
     }
-    entry->setField(QLatin1String("publisher"), value(resultMap, "publishers"));
-    entry->setField(QLatin1String("series"), value(resultMap, "series"));
-    entry->setField(QLatin1String("pages"), value(resultMap, "number_of_pages"));
-    entry->setField(QLatin1String("comments"), value(resultMap, "notes"));
+    entry->setField(QLatin1String("publisher"), mapValue(resultMap, "publishers"));
+    entry->setField(QLatin1String("series"), mapValue(resultMap, "series"));
+    entry->setField(QLatin1String("pages"), mapValue(resultMap, "number_of_pages"));
+    entry->setField(QLatin1String("comments"), mapValue(resultMap, "notes"));
 
     if(optionalFields().contains(QLatin1String("openlibrary"))) {
-      entry->setField(QLatin1String("openlibrary"), \
QLatin1String("http://openlibrary.org") + value(resultMap, "key")); +      \
entry->setField(QLatin1String("openlibrary"), QLatin1String("http://openlibrary.org") \
+ mapValue(resultMap, "key"));  }
 
     QStringList authors;
     foreach(const QVariant& authorMap, \
                resultMap.value(QLatin1String("authors")).toList()) {
-      const QString key = value(authorMap.toMap(), "key");
+      const QString key = mapValue(authorMap.toMap(), "key");
       if(!key.isEmpty()) {
         QUrl authorUrl(QString::fromLatin1(OPENLIBRARY_QUERY_URL));
         QUrlQuery q;
@@ -312,7 +312,7 @@ void OpenLibraryFetcher::slotComplete(KJob* job_) {
         QJsonDocument doc = QJsonDocument::fromJson(output.toUtf8());
         QJsonArray array = doc.array();
         QVariantMap authorResult = array.isEmpty() ? QVariantMap() : \
                array.at(0).toObject().toVariantMap();
-        const QString name = value(authorResult, "name");
+        const QString name = mapValue(authorResult, "name");
         if(!name.isEmpty()) {
           authors << name;
         }
@@ -324,7 +324,7 @@ void OpenLibraryFetcher::slotComplete(KJob* job_) {
 
     QStringList langs;
     foreach(const QVariant& langMap, \
                resultMap.value(QLatin1String("languages")).toList()) {
-      const QString key = value(langMap.toMap(), "key");
+      const QString key = mapValue(langMap.toMap(), "key");
       if(!key.isEmpty()) {
         QUrl langUrl(QString::fromLatin1(OPENLIBRARY_QUERY_URL));
         QUrlQuery q;
@@ -337,7 +337,7 @@ void OpenLibraryFetcher::slotComplete(KJob* job_) {
         QJsonDocument doc = QJsonDocument::fromJson(output.toUtf8());
         QJsonArray array = doc.array();
         QVariantMap langResult = array.isEmpty() ? QVariantMap() : \
                array.at(0).toObject().toVariantMap();
-        const QString name = value(langResult, "name");
+        const QString name = mapValue(langResult, "name");
         if(!name.isEmpty()) {
           langs << i18n(name.toUtf8().constData());
         }
@@ -370,7 +370,7 @@ QString OpenLibraryFetcher::getAuthorKeys(const QString& term_) {
   QJsonArray array = doc.array();
   myDebug() << "found" << array.count() << "authors";
   // right now, only use the first
-  return array.isEmpty() ? QString() : value(array.at(0).toObject().toVariantMap(), \
"key"); +  return array.isEmpty() ? QString() : \
mapValue(array.at(0).toObject().toVariantMap(), "key");  }
 
 Tellico::Fetch::ConfigWidget* OpenLibraryFetcher::configWidget(QWidget* parent_) \
const { @@ -407,19 +407,3 @@ void \
OpenLibraryFetcher::ConfigWidget::saveConfigHook(KConfigGroup&) {  QString \
OpenLibraryFetcher::ConfigWidget::preferredName() const {  return \
OpenLibraryFetcher::defaultName();  }
-
-// static
-QString OpenLibraryFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else if(v.canConvert(QVariant::Map)) {
-    return v.toMap().value(QLatin1String("value")).toString();
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/openlibraryfetcher.h b/src/fetch/openlibraryfetcher.h
index 1e975b02..db7c733d 100644
--- a/src/fetch/openlibraryfetcher.h
+++ b/src/fetch/openlibraryfetcher.h
@@ -94,8 +94,6 @@ private:
   QString getAuthorKeys(const QString& term);
   void endJob(KIO::StoredTransferJob* job);
 
-  static QString value(const QVariantMap& map, const char* name);
-
   QHash<int, Data::EntryPtr> m_entries;
   QList< QPointer<KIO::StoredTransferJob> > m_jobs;
 
diff --git a/src/fetch/themoviedbfetcher.cpp b/src/fetch/themoviedbfetcher.cpp
index 7d39e1d1..ba85de36 100644
--- a/src/fetch/themoviedbfetcher.cpp
+++ b/src/fetch/themoviedbfetcher.cpp
@@ -306,24 +306,24 @@ void TheMovieDBFetcher::slotComplete(KJob* job_) {
 }
 
 void TheMovieDBFetcher::populateEntry(Data::EntryPtr entry_, const QVariantMap& \
                resultMap_, bool fullData_) {
-  entry_->setField(QLatin1String("tmdb-id"), value(resultMap_, "id"));
-  entry_->setField(QLatin1String("title"), value(resultMap_, "title"));
-  entry_->setField(QLatin1String("year"),  value(resultMap_, \
"release_date").left(4)); +  entry_->setField(QLatin1String("tmdb-id"), \
mapValue(resultMap_, "id")); +  entry_->setField(QLatin1String("title"), \
mapValue(resultMap_, "title")); +  entry_->setField(QLatin1String("year"),  \
mapValue(resultMap_, "release_date").left(4));  
   QStringList directors, producers, writers, composers;
   QVariantList crewList = resultMap_.value(QLatin1String("credits")).toMap()
                                     .value(QLatin1String("crew")).toList();
   foreach(const QVariant& crew, crewList) {
     const QVariantMap crewMap = crew.toMap();
-    const QString job = value(crewMap, "job");
+    const QString job = mapValue(crewMap, "job");
     if(job == QLatin1String("Director")) {
-      directors += value(crewMap, "name");
+      directors += mapValue(crewMap, "name");
     } else if(job == QLatin1String("Producer")) {
-      producers += value(crewMap, "name");
+      producers += mapValue(crewMap, "name");
     } else if(job == QLatin1String("Screenplay")) {
-      writers += value(crewMap, "name");
+      writers += mapValue(crewMap, "name");
     } else if(job == QLatin1String("Original Music Composer")) {
-      composers += value(crewMap, "name");
+      composers += mapValue(crewMap, "name");
     }
   }
   entry_->setField(QLatin1String("director"), \
directors.join(FieldFormat::delimiterString())); @@ -337,19 +337,19 @@ void \
TheMovieDBFetcher::populateEntry(Data::EntryPtr entry_, const QVariantMap&  }
 
   if(entry_->collection()->hasField(QLatin1String("tmdb"))) {
-    entry_->setField(QLatin1String("tmdb"), \
QLatin1String("http://www.themoviedb.org/movie/") + value(resultMap_, "id")); +    \
entry_->setField(QLatin1String("tmdb"), \
QLatin1String("http://www.themoviedb.org/movie/") + mapValue(resultMap_, "id"));  }
   if(entry_->collection()->hasField(QLatin1String("imdb"))) {
-    entry_->setField(QLatin1String("imdb"), \
QLatin1String("http://www.imdb.com/title/") + value(resultMap_, "imdb_id")); +    \
entry_->setField(QLatin1String("imdb"), QLatin1String("http://www.imdb.com/title/") + \
mapValue(resultMap_, "imdb_id"));  }
   if(entry_->collection()->hasField(QLatin1String("origtitle"))) {
-    entry_->setField(QLatin1String("origtitle"), value(resultMap_, \
"original_title")); +    entry_->setField(QLatin1String("origtitle"), \
mapValue(resultMap_, "original_title"));  }
   if(entry_->collection()->hasField(QLatin1String("alttitle"))) {
     QStringList atitles;
     foreach(const QVariant& atitle, \
                resultMap_.value(QLatin1String("alternative_titles")).toMap()
                                                \
                .value(QLatin1String("titles")).toList()) {
-      atitles << value(atitle.toMap(), "title");
+      atitles << mapValue(atitle.toMap(), "title");
     }
     entry_->setField(QLatin1String("alttitle"), \
atitles.join(FieldFormat::rowDelimiterString()));  }
@@ -359,19 +359,19 @@ void TheMovieDBFetcher::populateEntry(Data::EntryPtr entry_, \
                const QVariantMap&
                                     .value(QLatin1String("cast")).toList();
   foreach(const QVariant& cast, castList) {
     QVariantMap castMap = cast.toMap();
-    actors << value(castMap, "name") + FieldFormat::columnDelimiterString() + \
value(castMap, "character"); +    actors << mapValue(castMap, "name") + \
FieldFormat::columnDelimiterString() + mapValue(castMap, "character");  }
   entry_->setField(QLatin1String("cast"), \
actors.join(FieldFormat::rowDelimiterString()));  
   QStringList studios;
   foreach(const QVariant& studio, \
                resultMap_.value(QLatin1String("production_companies")).toList()) {
-    studios << value(studio.toMap(), "name");
+    studios << mapValue(studio.toMap(), "name");
   }
   entry_->setField(QLatin1String("studio"), \
studios.join(FieldFormat::delimiterString()));  
   QStringList countries;
   foreach(const QVariant& country, \
                resultMap_.value(QLatin1String("production_countries")).toList()) {
-    QString name = value(country.toMap(), "name");
+    QString name = mapValue(country.toMap(), "name");
     if(name == QLatin1String("United States of America")) {
       name = QLatin1String("USA");
     }
@@ -381,16 +381,16 @@ void TheMovieDBFetcher::populateEntry(Data::EntryPtr entry_, \
const QVariantMap&  
   QStringList genres;
   foreach(const QVariant& genre, resultMap_.value(QLatin1String("genres")).toList()) \
                {
-    genres << value(genre.toMap(), "name");
+    genres << mapValue(genre.toMap(), "name");
   }
   entry_->setField(QLatin1String("genre"), \
genres.join(FieldFormat::delimiterString()));  
   // hard-coded poster size for now
-  QString cover = m_imageBase + QLatin1String("w342") + value(resultMap_, \
"poster_path"); +  QString cover = m_imageBase + QLatin1String("w342") + \
mapValue(resultMap_, "poster_path");  entry_->setField(QLatin1String("cover"), \
cover);  
-  entry_->setField(QLatin1String("running-time"), value(resultMap_, "runtime"));
-  entry_->setField(QLatin1String("plot"), value(resultMap_, "overview"));
+  entry_->setField(QLatin1String("running-time"), mapValue(resultMap_, "runtime"));
+  entry_->setField(QLatin1String("plot"), mapValue(resultMap_, "overview"));
 }
 
 void TheMovieDBFetcher::readConfiguration() {
@@ -415,7 +415,7 @@ void TheMovieDBFetcher::readConfiguration() {
   QJsonDocument doc = QJsonDocument::fromJson(data);
   QVariantMap resultMap = doc.object().toVariantMap();
 
-  m_imageBase = value(resultMap.value(QLatin1String("images")).toMap(), "base_url");
+  m_imageBase = mapValue(resultMap.value(QLatin1String("images")).toMap(), \
"base_url");  m_serverConfigDate = QDate::currentDate();
 }
 
@@ -515,17 +515,3 @@ QString TheMovieDBFetcher::ConfigWidget::preferredName() const {
 void TheMovieDBFetcher::ConfigWidget::slotLangChanged() {
   emit signalName(preferredName());
 }
-
-// static
-QString TheMovieDBFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/themoviedbfetcher.h b/src/fetch/themoviedbfetcher.h
index 7f944c7e..318166d6 100644
--- a/src/fetch/themoviedbfetcher.h
+++ b/src/fetch/themoviedbfetcher.h
@@ -97,8 +97,6 @@ private:
   void populateEntry(Data::EntryPtr entry, const QVariantMap& resultMap, bool \
fullData);  void readConfiguration();
 
-  static QString value(const QVariantMap& map, const char* name);
-
   bool m_started;
 
   QString m_locale;
diff --git a/src/fetch/vndbfetcher.cpp b/src/fetch/vndbfetcher.cpp
index 98fb806d..332094ad 100644
--- a/src/fetch/vndbfetcher.cpp
+++ b/src/fetch/vndbfetcher.cpp
@@ -255,16 +255,16 @@ void VNDBFetcher::slotComplete() {
     resultMap = result.toMap();
 
     Data::EntryPtr entry(new Data::Entry(coll));
-    entry->setField(QLatin1String("title"), value(resultMap, "title"));
-    entry->setField(QLatin1String("year"), value(resultMap, "released").left(4));
+    entry->setField(QLatin1String("title"), mapValue(resultMap, "title"));
+    entry->setField(QLatin1String("year"), mapValue(resultMap, "released").left(4));
     entry->setField(QLatin1String("genre"), i18n("Visual Novel"));
-    entry->setField(QLatin1String("description"), value(resultMap, "description"));
-    entry->setField(QLatin1String("cover"), value(resultMap, "image"));
+    entry->setField(QLatin1String("description"), mapValue(resultMap, \
"description")); +    entry->setField(QLatin1String("cover"), mapValue(resultMap, \
"image"));  if(optionalFields().contains(QLatin1String("origtitle"))) {
-      entry->setField(QLatin1String("origtitle"), value(resultMap, "original"));
+      entry->setField(QLatin1String("origtitle"), mapValue(resultMap, "original"));
     }
     if(optionalFields().contains(QLatin1String("alias"))) {
-      const QString aliases = value(resultMap, "aliases");
+      const QString aliases = mapValue(resultMap, "aliases");
       entry->setField(QLatin1String("alias"), \
aliases.split(QLatin1String("\n")).join(FieldFormat::delimiterString()));  }
 
@@ -333,19 +333,3 @@ void VNDBFetcher::ConfigWidget::saveConfigHook(KConfigGroup&) {
 QString VNDBFetcher::ConfigWidget::preferredName() const {
   return VNDBFetcher::defaultName();
 }
-
-// static
-QString VNDBFetcher::value(const QVariantMap& map, const char* name) {
-  const QVariant v = map.value(QLatin1String(name));
-  if(v.isNull())  {
-    return QString();
-  } else if(v.canConvert(QVariant::String)) {
-    return v.toString();
-  } else if(v.canConvert(QVariant::StringList)) {
-    return v.toStringList().join(Tellico::FieldFormat::delimiterString());
-  } else if(v.canConvert(QVariant::Map)) {
-    return v.toMap().value(QLatin1String("value")).toString();
-  } else {
-    return QString();
-  }
-}
diff --git a/src/fetch/vndbfetcher.h b/src/fetch/vndbfetcher.h
index c2aa06f7..13055477 100644
--- a/src/fetch/vndbfetcher.h
+++ b/src/fetch/vndbfetcher.h
@@ -95,8 +95,6 @@ private:
   virtual void search() Q_DECL_OVERRIDE;
   virtual FetchRequest updateRequest(Data::EntryPtr entry) Q_DECL_OVERRIDE;
 
-  static QString value(const QVariantMap& map, const char* name);
-
   QHash<int, Data::EntryPtr> m_entries;
 
   bool m_started;
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 49650fee..e5cc4b26 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -7,7 +7,7 @@ SET( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
 # which is generated in the build directory
 INCLUDE_DIRECTORIES( ${Tellico_BINARY_DIR}/src )
 
-add_executable(entitytest entitytest.cpp)
+add_executable(entitytest entitytest.cpp ../fieldformat.cpp)
 ecm_mark_nongui_executable(entitytest)
 add_test(entitytest entitytest)
 ecm_mark_as_test(entitytest)
@@ -55,7 +55,7 @@ add_test(comparisontest comparisontest)
 ecm_mark_as_test(comparisontest)
 TARGET_LINK_LIBRARIES(comparisontest utils core Qt5::Test)
 
-add_executable(imagetest imagetest.cpp ../utils/tellico_utils.cpp \
../utils/guiproxy.cpp ../utils/cursorsaver.cpp) +add_executable(imagetest \
imagetest.cpp ../utils/tellico_utils.cpp ../utils/guiproxy.cpp \
../utils/cursorsaver.cpp ../fieldformat.cpp)  ecm_mark_nongui_executable(imagetest)
 add_test(imagetest imagetest)
 ecm_mark_as_test(imagetest)
diff --git a/src/utils/string_utils.cpp b/src/utils/string_utils.cpp
index b060438b..765e0fca 100644
--- a/src/utils/string_utils.cpp
+++ b/src/utils/string_utils.cpp
@@ -23,6 +23,7 @@
  ***************************************************************************/
 
 #include "string_utils.h"
+#include "../fieldformat.h"
 
 #include <KCharsets>
 #include <KLocalizedString>
@@ -30,6 +31,7 @@
 
 #include <QRegExp>
 #include <QTextCodec>
+#include <QVariant>
 
 namespace {
   static const int STRING_STORE_SIZE = 997; // too big, too small?
@@ -130,3 +132,33 @@ QString Tellico::removeAccents(const QString& value_) {
   }
   return value2;
 }
+
+QString Tellico::mapValue(const QVariantMap& map, const char* name) {
+  const QVariant v = map.value(QLatin1String(name));
+  if(v.isNull())  {
+    return QString();
+  } else if(v.canConvert(QVariant::String)) {
+    return v.toString();
+  } else if(v.canConvert(QVariant::StringList)) {
+    return v.toStringList().join(FieldFormat::delimiterString());
+  } else if(v.canConvert(QVariant::Map)) {
+    // FilmasterFetcher, OpenLibraryFetcher and VNDBFetcher depend on the default \
"value" field +    return v.toMap().value(QLatin1String("value")).toString();
+  } else {
+    return QString();
+  }
+}
+
+QString Tellico::mapValue(const QVariantMap& map, const char* object, const char* \
name) { +  const QVariant v = map.value(QLatin1String(object));
+  if(v.isNull())  {
+    return QString();
+  } else if(v.canConvert(QVariant::Map)) {
+    return mapValue(v.toMap(), name);
+  } else if(v.canConvert(QVariant::List)) {
+    const QVariantList list = v.toList();
+    return list.isEmpty() ? QString() : mapValue(list.at(0).toMap(), name);
+  } else {
+    return QString();
+  }
+}
diff --git a/src/utils/string_utils.h b/src/utils/string_utils.h
index 617c7af5..37b5db8f 100644
--- a/src/utils/string_utils.h
+++ b/src/utils/string_utils.h
@@ -25,11 +25,12 @@
 #ifndef STRING_UTILS_H
 #define STRING_UTILS_H
 
-#include <Qt>
-
 class QByteArray;
 class QString;
 
+#include <Qt>
+#include <QMetaType>
+
 /**
  * This file contains utility functions for manipulating strings.
  *
@@ -62,6 +63,10 @@ namespace Tellico {
 
   QString minutes(int seconds);
   QString fromHtmlData(const QByteArray& data, const char* codecName = nullptr);
+
+  // helper methods for the QVariantMaps used by the JSON importers
+  QString mapValue(const QVariantMap& map, const char* object);
+  QString mapValue(const QVariantMap& map, const char* object, const char* name);
 }
 
 #endif


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic