Git commit d78938ef5fce9d3de371d7958b1135d0604a7409 by Robby Stephenson.
Committed on 30/09/2023 at 03:58.
Pushed by rstephenson into branch 'master'.

Add importer for Discogs collection

Only read public collection folders for now

BUG: 446262
FIXED-IN: 3.5.2

M  +4    -0    ChangeLog
M  +7    -0    doc/importing-exporting.docbook
M  +1    -0    icons/CMakeLists.txt
A  +-    --    icons/discogs.png
M  +1    -0    icons/icons.qrc
M  +10   -8    src/fetch/discogsfetcher.cpp
M  +8    -0    src/importdialog.cpp
M  +3    -0    src/mainwindow.cpp
M  +2    -1    src/tellicoui.rc
M  +6    -1    src/tests/CMakeLists.txt
A  +95   -0    src/tests/discogstest.cpp     [License: GPL (v2/3)]
C  +10   -69   src/tests/discogstest.h [from: src/translators/translators.h - 
061% similarity]
M  +1    -0    src/translators/CMakeLists.txt
A  +206  -0    src/translators/discogsimporter.cpp     [License: GPL (v2/3)]
C  +46   -69   src/translators/discogsimporter.h [from: 
src/translators/translators.h - 063% similarity]
M  +2    -1    src/translators/translators.h

https://invent.kde.org/office/tellico/-/commit/d78938ef5fce9d3de371d7958b1135d0604a7409

diff --git a/ChangeLog b/ChangeLog
index 053f69d0..850a01c6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2023-09-28  Robby Stephenson  <ro...@periapsis.org>
+
+       * Added importer for Discogs collections (Bug 446262).
+
 2023-09-27  Robby Stephenson  <ro...@periapsis.org>
 
        * Added fallback title for entries with no title field (Bug 231867).
diff --git a/doc/importing-exporting.docbook b/doc/importing-exporting.docbook
index 8f4a14d9..6ecec2ab 100644
--- a/doc/importing-exporting.docbook
+++ b/doc/importing-exporting.docbook
@@ -200,6 +200,13 @@ The <ulink 
url="https://en.wikipedia.org/wiki/RIS_(file_format)"><acronym>RIS</a
 </para>
 </sect3>
 
+<sect3 id="importing-discogs">
+<title>Importing Discogs Collection</title>
+<para>
+<ulink url="https://www.discogs.com";>Discogs</ulink> is an online database and 
marketplace of music releases. &appname; can import the list of music releases 
in a user's collection, given  the user name, as long as the collection is set 
to be publicly accessible.
+</para>
+</sect3>
+
 </sect2>
 
 <sect2 id="importing-file-listing">
diff --git a/icons/CMakeLists.txt b/icons/CMakeLists.txt
index cdbac71a..bdef76a4 100644
--- a/icons/CMakeLists.txt
+++ b/icons/CMakeLists.txt
@@ -16,6 +16,7 @@ set(PIC_FILES
     comic.png
     datacrow.png
     deliciouslibrary.png
+    discogs.png
     file.png
     game.png
     gcstar.png
diff --git a/icons/discogs.png b/icons/discogs.png
new file mode 100644
index 00000000..1202903b
Binary files /dev/null and b/icons/discogs.png differ
diff --git a/icons/icons.qrc b/icons/icons.qrc
index 5ac7f915..e8d6cf22 100644
--- a/icons/icons.qrc
+++ b/icons/icons.qrc
@@ -15,6 +15,7 @@
     <file alias="collectorz.png">collectorz.png</file>
     <file alias="comic.png">comic.png</file>
     <file alias="deliciouslibrary.png">deliciouslibrary.png</file>
+    <file alias="discogs.png">discogs.png</file>
     <file alias="file.png">file.png</file>
     <file alias="game.png">game.png</file>
     <file alias="gcstar.png">gcstar.png</file>
diff --git a/src/fetch/discogsfetcher.cpp b/src/fetch/discogsfetcher.cpp
index d1ed3ea4..d3e4ceff 100644
--- a/src/fetch/discogsfetcher.cpp
+++ b/src/fetch/discogsfetcher.cpp
@@ -149,8 +149,8 @@ void DiscogsFetcher::continueSearch() {
 
   m_job = KIO::storedGet(u, KIO::NoReload, KIO::HideProgressInfo);
   m_job->addMetaData(QLatin1String("SendUserAgent"), QLatin1String("true"));
-  m_job->addMetaData(QStringLiteral("UserAgent"), QStringLiteral("Tellico/%1")
-                                                                
.arg(QStringLiteral(TELLICO_VERSION)));
+  m_job->addMetaData(QStringLiteral("UserAgent"),
+                     
QStringLiteral("Tellico/%1").arg(QStringLiteral(TELLICO_VERSION)));
   KJobWidgets::setWindow(m_job, GUI::Proxy::widget());
   connect(m_job.data(), &KJob::result, this, &DiscogsFetcher::slotComplete);
 }
@@ -392,8 +392,9 @@ void DiscogsFetcher::populateEntry(Data::EntryPtr entry_, 
const QVariantMap& res
 
   QStringList labels, catnos;
   foreach(const QVariant& label, 
resultMap_.value(QLatin1String("labels")).toList()) {
-    labels << mapValue(label.toMap(), "name");
-    catnos << mapValue(label.toMap(), "catno");
+    const QVariantMap labelMap = label.toMap();
+    labels << mapValue(labelMap, "name");
+    catnos << mapValue(labelMap, "catno");
   }
   entry_->setField(QStringLiteral("label"), 
labels.join(FieldFormat::delimiterString()));
   if(entry_->collection()->hasField(QStringLiteral("catno"))) {
@@ -482,9 +483,10 @@ void DiscogsFetcher::populateEntry(Data::EntryPtr entry_, 
const QVariantMap& res
 
   if(entry_->collection()->hasField(QStringLiteral("producer"))) {
     QStringList producers;
-    foreach(const QVariant& extraartist, 
resultMap_.value(QLatin1String("extraartists")).toList()) {
-      if(mapValue(extraartist.toMap(), 
"role").contains(QStringLiteral("Producer"))) {
-        producers << mapValue(extraartist.toMap(), "name");
+    foreach(const QVariant& extraArtist, 
resultMap_.value(QLatin1String("extraartists")).toList()) {
+      const QVariantMap extraArtistMap = extraArtist.toMap();
+      if(mapValue(extraArtistMap, 
"role").contains(QStringLiteral("Producer"))) {
+        producers << mapValue(extraArtistMap, "name");
       }
     }
     entry_->setField(QStringLiteral("producer"), 
producers.join(FieldFormat::delimiterString()));
@@ -534,7 +536,7 @@ DiscogsFetcher::ConfigWidget::ConfigWidget(QWidget* 
parent_, const DiscogsFetche
   // richtext gets weird with size
   al->setMinimumWidth(al->sizeHint().width());
 
-  QLabel* label = new QLabel(i18n("User token: "), optionsWidget());
+  QLabel* label = new QLabel(i18n("User token:"), optionsWidget());
   l->addWidget(label, ++row, 0);
 
   m_apiKeyEdit = new QLineEdit(optionsWidget());
diff --git a/src/importdialog.cpp b/src/importdialog.cpp
index c4b22525..ec889aea 100644
--- a/src/importdialog.cpp
+++ b/src/importdialog.cpp
@@ -56,6 +56,7 @@
 #include "translators/datacrowimporter.h"
 #include "translators/marcimporter.h"
 #include "translators/ebookimporter.h"
+#include "translators/discogsimporter.h"
 #include "utils/datafileregistry.h"
 
 #include <KLocalizedString>
@@ -333,6 +334,11 @@ Tellico::Import::Importer* 
ImportDialog::importer(Tellico::Import::Format format
     case Import::EBook:
       importer = new Import::EBookImporter(urls_);
       break;
+
+    case Import::Discogs:
+      CHECK_SIZE;
+      importer = new Import::DiscogsImporter();
+      break;
   }
   if(!importer) {
     myWarning() << "importer not created!";
@@ -433,6 +439,7 @@ QString ImportDialog::fileFilter(Tellico::Import::Format 
format_) {
     case Import::BoardGameGeek:
     case Import::LibraryThing:
     case Import::MARC:
+    case Import::Discogs:
       break;
   }
 
@@ -452,6 +459,7 @@ Tellico::Import::Target 
ImportDialog::importTarget(Tellico::Import::Format forma
     case Import::Goodreads:
     case Import::BoardGameGeek:
     case Import::LibraryThing:
+    case Import::Discogs:
       return Import::None;
     default:
       return Import::File;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 1c2fd1c5..fc56d49f 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -456,6 +456,9 @@ void MainWindow::initActions() {
   action->setEnabled(false);
 #endif
 
+  IMPORT_ACTION(Import::Discogs, "file_import_discogs", i18n("Import Discogs 
Collection..."),
+                i18n("Import a collection from Discogs.com"), 
QIcon::fromTheme(QStringLiteral(":/icons/discogs")));
+
   IMPORT_ACTION(Import::GCstar, "file_import_gcstar", i18n("Import GCstar 
Data..."),
                 i18n("Import a GCstar data file"),
                 QIcon::fromTheme(QStringLiteral("gcstar"), 
QIcon(QLatin1String(":/icons/gcstar"))));
diff --git a/src/tellicoui.rc b/src/tellicoui.rc
index febecf63..e05d6482 100644
--- a/src/tellicoui.rc
+++ b/src/tellicoui.rc
@@ -1,6 +1,6 @@
 <?xml version = '1.0'?>
 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui version="44" name="tellico">
+<kpartgui version="46" name="tellico">
  <MenuBar>
   <Menu name="file">
    <text>&amp;File</text>
@@ -45,6 +45,7 @@
     <Separator/>
     <Action name="file_import_freedb"/>
     <Action name="file_import_audiofile"/>
+    <Action name="file_import_discogs"/>
     <Separator/>
     <Action name="file_import_amc"/>
     <Action name="file_import_griffith"/>
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index f2844a0e..aac02709 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -280,13 +280,18 @@ ecm_add_test(datacrowtest.cpp
     LINK_LIBRARIES ${TELLICO_TEST_LIBS} translatorstest
 )
 
-
 ecm_add_test(delicioustest.cpp
              ../translators/deliciousimporter.cpp
     TEST_NAME delicioustest
     LINK_LIBRARIES ${TELLICO_TEST_LIBS} translatorstest rtf2html-tellico
 )
 
+ecm_add_test(discogstest.cpp
+             ../translators/discogsimporter.cpp
+    TEST_NAME discogstest
+    LINK_LIBRARIES ${TELLICO_TEST_LIBS} translatorstest
+)
+
 ecm_add_test(fieldwidgettest.cpp
              ../gui/boolfieldwidget.cpp
              ../gui/choicefieldwidget.cpp
diff --git a/src/tests/discogstest.cpp b/src/tests/discogstest.cpp
new file mode 100644
index 00000000..69c1155b
--- /dev/null
+++ b/src/tests/discogstest.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+    Copyright (C) 2023 Robby Stephenson <ro...@periapsis.org>
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or         *
+ *   modify it under the terms of the GNU General Public License as        *
+ *   published by the Free Software Foundation; either version 2 of        *
+ *   the License or (at your option) version 3 or any later version        *
+ *   accepted by the membership of KDE e.V. (or its successor approved     *
+ *   by the membership of KDE e.V.), which shall act as a proxy            *
+ *   defined in Section 14 of version 3 of the license.                    *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <config.h>
+#include "discogstest.h"
+
+#include "../translators/discogsimporter.h"
+#include "../collections/musiccollection.h"
+#include "../collectionfactory.h"
+#include "../images/imagefactory.h"
+
+#include <KConfig>
+#include <KSharedConfig>
+#include <KConfigGroup>
+#include <KLocalizedString>
+
+#include <QTest>
+#include <QNetworkInterface>
+#include <QStandardPaths>
+
+QTEST_GUILESS_MAIN( DiscogsTest )
+
+static bool hasNetwork() {
+#ifdef ENABLE_NETWORK_TESTS
+  foreach(const QNetworkInterface& net, QNetworkInterface::allInterfaces()) {
+    if(net.flags().testFlag(QNetworkInterface::IsUp) && 
!net.flags().testFlag(QNetworkInterface::IsLoopBack)) {
+      return true;
+    }
+  }
+#endif
+  return false;
+}
+
+void DiscogsTest::initTestCase() {
+  QStandardPaths::setTestModeEnabled(true);
+  KLocalizedString::setApplicationDomain("tellico");
+  Tellico::RegisterCollection<Tellico::Data::MusicCollection> 
registerMusic(Tellico::Data::Collection::Album, "album");
+  Tellico::ImageFactory::init();
+}
+
+void DiscogsTest::testImport() {
+  if(!hasNetwork()) QSKIP("This test requires network access", SkipSingle);
+
+  Tellico::Import::DiscogsImporter imp;
+  QVERIFY(!imp.canImport(Tellico::Data::Collection::Book));
+  QVERIFY(imp.canImport(Tellico::Data::Collection::Album));
+
+  KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), 
KConfig::SimpleConfig);
+  KConfigGroup cg(config, QStringLiteral("ImportOptions - Discogs"));
+  cg.writeEntry("User ID", QStringLiteral("tellico-robby"));
+  // need to add token to get images
+  config->sync();
+  imp.setConfig(config);
+
+  Tellico::Data::CollPtr coll(imp.collection());
+  QVERIFY(coll);
+  QCOMPARE(coll->type(), Tellico::Data::Collection::Album);
+
+  Tellico::Data::EntryList entries = coll->entries();
+  QVERIFY(!entries.isEmpty());
+  Tellico::Data::EntryPtr entry = entries.at(0);
+  QVERIFY(entry);
+  QCOMPARE(entry->field(QStringLiteral("title")), QStringLiteral("Les 
Misérables"));
+  QCOMPARE(entry->field(QStringLiteral("year")), QStringLiteral("1985"));
+  QCOMPARE(entry->field(QStringLiteral("medium")), QStringLiteral("Compact 
Disc"));
+  QCOMPARE(entry->field(QStringLiteral("label")), QStringLiteral("First Night 
Records"));
+  QCOMPARE(entry->field(QStringLiteral("genre")), QStringLiteral("Musical"));
+  QCOMPARE(entry->field(QStringLiteral("artist")), QStringLiteral("Alain 
Boublil; Claude-Michel Schönberg"));
+  QCOMPARE(entry->field(QStringLiteral("rating")), QStringLiteral("4"));
+
+//  QVERIFY(!entry->field(QStringLiteral("cover")).isEmpty());
+//  QVERIFY(!entry->field(QStringLiteral("cover")).contains(QLatin1Char('/')));
+//  QVERIFY(!entry->field(QStringLiteral("comments")).isEmpty());
+}
diff --git a/src/translators/translators.h b/src/tests/discogstest.h
similarity index 61%
copy from src/translators/translators.h
copy to src/tests/discogstest.h
index 074bf6bd..14fa1b3f 100644
--- a/src/translators/translators.h
+++ b/src/tests/discogstest.h
@@ -1,5 +1,5 @@
 /***************************************************************************
-    Copyright (C) 2003-2009 Robby Stephenson <ro...@periapsis.org>
+    Copyright (C) 2023 Robby Stephenson <ro...@periapsis.org>
  ***************************************************************************/
 
 /***************************************************************************
@@ -22,76 +22,17 @@
  *                                                                         *
  ***************************************************************************/
 
-#ifndef TRANSLATORS_H
-#define TRANSLATORS_H
+#ifndef DISCOGSTEST_H
+#define DISCOGSTEST_H
 
-namespace Tellico {
-  namespace Import {
-    enum Format {
-      TellicoXML = 0,
-      Bibtex,
-      Bibtexml,
-      CSV,
-      XSLT,
-      AudioFile,
-      MODS,
-      Alexandria,
-      FreeDB,
-      RIS,
-      GCstar,
-      FileListing,
-      GRS1,
-      AMC,
-      Griffith,
-      PDF,
-      Referencer,
-      Delicious,
-      Goodreads,
-      CIW,
-      VinoXML,
-      BoardGameGeek,
-      LibraryThing,
-      Collectorz,
-      DataCrow,
-      MARC,
-      EBook
-    };
+#include <QObject>
 
-    enum Action {
-      Replace,
-      Append,
-      Merge
-    };
+class DiscogsTest : public QObject {
+Q_OBJECT
 
-    enum Target {
-      None,
-      File,
-      Dir
-    };
-  }
-
-  namespace Export {
-    enum Format {
-      TellicoXML = 0,
-      TellicoZip,
-      Bibtex,
-      Bibtexml,
-      HTML,
-      CSV,
-      XSLT,
-      Text,
-      PilotDB, // Deprecated
-      Alexandria,
-      ONIX,
-      GCstar
-    };
-
-    enum Target {
-      None,
-      File,
-      Dir
-    };
-  }
-}
+private Q_SLOTS:
+  void initTestCase();
+  void testImport();
+};
 
 #endif
diff --git a/src/translators/CMakeLists.txt b/src/translators/CMakeLists.txt
index 1d92c123..d9f9a4c9 100644
--- a/src/translators/CMakeLists.txt
+++ b/src/translators/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(translators_STAT_SRCS
    datacrowimporter.cpp
    dataimporter.cpp
    deliciousimporter.cpp
+   discogsimporter.cpp
    ebookimporter.cpp
    exporter.cpp
    filelistingimporter.cpp
diff --git a/src/translators/discogsimporter.cpp 
b/src/translators/discogsimporter.cpp
new file mode 100644
index 00000000..3bb4aacd
--- /dev/null
+++ b/src/translators/discogsimporter.cpp
@@ -0,0 +1,206 @@
+/***************************************************************************
+    Copyright (C) 2023 Robby Stephenson <ro...@periapsis.org>
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or         *
+ *   modify it under the terms of the GNU General Public License as        *
+ *   published by the Free Software Foundation; either version 2 of        *
+ *   the License or (at your option) version 3 or any later version        *
+ *   accepted by the membership of KDE e.V. (or its successor approved     *
+ *   by the membership of KDE e.V.), which shall act as a proxy            *
+ *   defined in Section 14 of version 3 of the license.                    *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "discogsimporter.h"
+#include "../collections/musiccollection.h"
+#include "../images/imagefactory.h"
+#include "../core/filehandler.h"
+#include "../utils/string_utils.h"
+#include "../tellico_debug.h"
+
+#include <KConfigGroup>
+#include <KLocalizedString>
+
+#include <QLineEdit>
+#include <QVBoxLayout>
+#include <QFormLayout>
+#include <QGroupBox>
+#include <QUrlQuery>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QFile>
+
+namespace {
+  static const char* DISCOGS_API_URL = "https://api.discogs.com";;
+}
+
+using Tellico::Import::DiscogsImporter;
+
+DiscogsImporter::DiscogsImporter() : Import::Importer(), m_widget(nullptr), 
m_userEdit(nullptr), m_tokenEdit(nullptr) {
+}
+
+void DiscogsImporter::setConfig(KSharedConfig::Ptr config_) {
+  m_config = config_;
+}
+
+bool DiscogsImporter::canImport(int type) const {
+  return type == Data::Collection::Album;
+}
+
+Tellico::Data::CollPtr DiscogsImporter::collection() {
+  if(m_coll) {
+    return m_coll;
+  }
+
+  if(!m_config) {
+    m_config = KSharedConfig::openConfig();
+  }
+
+  KConfigGroup cg(m_config, QStringLiteral("ImportOptions - Discogs"));
+  m_user = cg.readEntry("User ID");
+  m_token = cg.readEntry("API Key"); // same config name as used in 
discogsfetcher
+
+  if(m_widget) {
+    m_user = m_userEdit->text().trimmed();
+    m_token = m_tokenEdit->text().trimmed();
+  }
+
+  if(m_user.isEmpty()) {
+    setStatusMessage(i18n("A valid user ID must be entered."));
+    return Data::CollPtr();
+  }
+
+  m_coll = new Data::MusicCollection(true);
+  loadPage(1);
+  return m_coll;
+}
+
+void DiscogsImporter::loadPage(int page_) {
+  QUrl u(QString::fromLatin1(DISCOGS_API_URL));
+  
u.setPath(QStringLiteral("/users/%1/collection/folders/0/releases").arg(m_user));
+  QUrlQuery q;
+  q.addQueryItem(QLatin1String("page"), QString::number(page_));
+  if(!m_token.isEmpty()) {
+    q.addQueryItem(QStringLiteral("token"), m_token);
+  }
+  u.setQuery(q);
+//  myDebug() << u;
+  const QByteArray data = FileHandler::readDataFile(u, true /* quiet */);
+
+#if 0
+  myWarning() << "Remove output debug from discogsimporter.cpp";
+  QFile f(QLatin1String("/tmp/discogs.json"));
+  if(f.open(QIODevice::WriteOnly)) {
+    QDataStream t(&f);
+    t << data;
+  }
+  f.close();
+#endif
+
+  QJsonDocument doc = QJsonDocument::fromJson(data);
+  const QVariantMap resultMap = doc.object().toVariantMap();
+  if(resultMap.contains(QStringLiteral("message")) && mapValue(resultMap, 
"id").isEmpty()) {
+    const auto& msg = mapValue(resultMap, "message");
+    myLog() << "DiscogsFetcher -" << msg;
+  }
+  const int totalPages = mapValue(resultMap, "pagination", "pages").toInt();
+//  myDebug() << "total pages:" << totalPages << "current:" << page_;
+  foreach(const QVariant& release, 
resultMap.value(QLatin1String("releases")).toList()) {
+    Data::EntryPtr entry(new Data::Entry(m_coll));
+    const auto releaseMap = release.toMap();
+    populateEntry(entry, 
releaseMap.value(QLatin1String("basic_information")).toMap());
+
+    const QString rating = mapValue(releaseMap, "rating");
+    if(!rating.isEmpty() && rating != QLatin1String("0")) {
+      entry->setField(QStringLiteral("rating"), rating);
+    }
+    entry->setField(QStringLiteral("comments"), mapValue(releaseMap, "notes", 
"value"));
+    m_coll->addEntries(entry);
+  }
+
+  if(totalPages > page_) {
+    loadPage(page_+1);
+  }
+}
+
+void DiscogsImporter::populateEntry(Data::EntryPtr entry_, const QVariantMap& 
releaseMap_) {
+  entry_->setField(QStringLiteral("title"), mapValue(releaseMap_, "title"));
+  const QString year = mapValue(releaseMap_, "year");
+  if(year != QLatin1String("0")) {
+    entry_->setField(QStringLiteral("year"), year);
+  }
+  // the styles value seems more like genres than the actual genres value
+  entry_->setField(QStringLiteral("genre"),  mapValue(releaseMap_, "styles"));
+
+  QStringList labels;
+  foreach(const QVariant& label, 
releaseMap_.value(QLatin1String("labels")).toList()) {
+    labels << mapValue(label.toMap(), "name");
+  }
+  entry_->setField(QStringLiteral("label"), 
labels.join(FieldFormat::delimiterString()));
+
+  QStringList artists;
+  foreach(const QVariant& artist, 
releaseMap_.value(QLatin1String("artists")).toList()) {
+    artists << mapValue(artist.toMap(), "name");
+  }
+  artists.removeDuplicates(); // sometimes the same value is repeated
+  entry_->setField(QStringLiteral("artist"), 
artists.join(FieldFormat::delimiterString()));
+
+  foreach(const QVariant& format, 
releaseMap_.value(QLatin1String("formats")).toList()) {
+    const QString formatName = mapValue(format.toMap(), "name");
+    if(formatName == QLatin1String("CD")) {
+      entry_->setField(QStringLiteral("medium"), i18n("Compact Disc"));
+    } else if(formatName == QLatin1String("Vinyl")) {
+      entry_->setField(QStringLiteral("medium"), i18n("Vinyl"));
+    } else if(formatName == QLatin1String("Cassette")) {
+      entry_->setField(QStringLiteral("medium"), i18n("Cassette"));
+    } else if(formatName == QLatin1String("DVD")) {
+      // sometimes a CD and DVD both are included. If we're using the CD, 
ignore the DVD
+      entry_->setField(QStringLiteral("medium"), i18n("DVD"));
+    }
+  }
+
+  QString coverUrl = mapValue(releaseMap_, "cover_image");
+  if(coverUrl.isEmpty()) {
+    coverUrl = mapValue(releaseMap_, "thumb");
+  }
+  if(!coverUrl.isEmpty()) {
+    const QString id = ImageFactory::addImage(QUrl::fromUserInput(coverUrl), 
true /* quiet */);
+    // empty image ID is ok
+    entry_->setField(QStringLiteral("cover"), id);
+  }
+}
+
+QWidget* DiscogsImporter::widget(QWidget* parent_) {
+  if(m_widget) {
+    return m_widget;
+  }
+  m_widget = new QWidget(parent_);
+  QVBoxLayout* l = new QVBoxLayout(m_widget);
+
+  QGroupBox* gbox = new QGroupBox(i18n("Discogs Options"), m_widget);
+  QFormLayout* lay = new QFormLayout(gbox);
+
+  m_userEdit = new QLineEdit(gbox);
+  m_userEdit->setText(m_user);
+  m_tokenEdit = new QLineEdit(gbox);
+  m_tokenEdit->setText(m_token);
+
+  lay->addRow(i18n("User ID:"), m_userEdit);
+  lay->addRow(i18n("User token:"), m_tokenEdit);
+
+  l->addWidget(gbox);
+  l->addStretch(1);
+
+  return m_widget;
+}
diff --git a/src/translators/translators.h b/src/translators/discogsimporter.h
similarity index 63%
copy from src/translators/translators.h
copy to src/translators/discogsimporter.h
index 074bf6bd..05d2fb95 100644
--- a/src/translators/translators.h
+++ b/src/translators/discogsimporter.h
@@ -1,5 +1,5 @@
 /***************************************************************************
-    Copyright (C) 2003-2009 Robby Stephenson <ro...@periapsis.org>
+    Copyright (C) 2023 Robby Stephenson <ro...@periapsis.org>
  ***************************************************************************/
 
 /***************************************************************************
@@ -22,76 +22,53 @@
  *                                                                         *
  ***************************************************************************/
 
-#ifndef TRANSLATORS_H
-#define TRANSLATORS_H
+#ifndef TELLICO_IMPORT_DISCOGSIMPORTER_H
+#define TELLICO_IMPORT_DISCOGSIMPORTER_H
+
+#include "importer.h"
+
+#include <KSharedConfig>
+
+class QLineEdit;
 
 namespace Tellico {
   namespace Import {
-    enum Format {
-      TellicoXML = 0,
-      Bibtex,
-      Bibtexml,
-      CSV,
-      XSLT,
-      AudioFile,
-      MODS,
-      Alexandria,
-      FreeDB,
-      RIS,
-      GCstar,
-      FileListing,
-      GRS1,
-      AMC,
-      Griffith,
-      PDF,
-      Referencer,
-      Delicious,
-      Goodreads,
-      CIW,
-      VinoXML,
-      BoardGameGeek,
-      LibraryThing,
-      Collectorz,
-      DataCrow,
-      MARC,
-      EBook
-    };
-
-    enum Action {
-      Replace,
-      Append,
-      Merge
-    };
-
-    enum Target {
-      None,
-      File,
-      Dir
-    };
-  }
-
-  namespace Export {
-    enum Format {
-      TellicoXML = 0,
-      TellicoZip,
-      Bibtex,
-      Bibtexml,
-      HTML,
-      CSV,
-      XSLT,
-      Text,
-      PilotDB, // Deprecated
-      Alexandria,
-      ONIX,
-      GCstar
-    };
-
-    enum Target {
-      None,
-      File,
-      Dir
-    };
-  }
-}
 
+/**
+ * @author Robby Stephenson
+*/
+class DiscogsImporter : public Importer {
+Q_OBJECT
+
+public:
+  /**
+   */
+  DiscogsImporter();
+
+  virtual Data::CollPtr collection() Q_DECL_OVERRIDE;
+  virtual bool canImport(int type) const Q_DECL_OVERRIDE;
+
+  virtual QWidget* widget(QWidget* parent) Q_DECL_OVERRIDE;
+
+  void setConfig(KSharedConfig::Ptr config);
+
+public Q_SLOTS:
+  void slotCancel() Q_DECL_OVERRIDE {}
+
+private:
+  void loadPage(int page);
+  void populateEntry(Data::EntryPtr entry, const QVariantMap& releaseMap);
+
+  Data::CollPtr m_coll;
+  QWidget* m_widget;
+  QLineEdit* m_userEdit;
+  QLineEdit* m_tokenEdit;
+  KSharedConfig::Ptr m_config;
+
+  QString m_user;
+  QString m_token;
+};
+
+  } // end namespace
+} // end namespace
 #endif
diff --git a/src/translators/translators.h b/src/translators/translators.h
index 074bf6bd..1e0edf9c 100644
--- a/src/translators/translators.h
+++ b/src/translators/translators.h
@@ -54,7 +54,8 @@ namespace Tellico {
       Collectorz,
       DataCrow,
       MARC,
-      EBook
+      EBook,
+      Discogs
     };
 
     enum Action {

Reply via email to