[office/tellico] /: Allow multiple values for upcitemdb search

Robby Stephenson <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit bc5517accb2036b2b8571a17fa6f5d399309a548 by Robby Stephenson.
Committed on 01/08/2026 at 00:49.
Pushed by rstephenson into branch 'master'.

Allow multiple values for upcitemdb search

M  +4    -0    ChangeLog
M  +34   -20   src/fetch/upcitemdbfetcher.cpp
M  +3    -1    src/fetch/upcitemdbfetcher.h
M  +13   -0    src/tests/upcitemdbfetchertest.cpp
M  +1    -0    src/tests/upcitemdbfetchertest.h

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

diff --git a/ChangeLog b/ChangeLog
index a8615c24f..016f4a30c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2026-07-31  Robby Stephenson  <[email protected]>
+
+	* Updated UPCItemDb data source to allow multiple search values.
+
 2026-07-26  Robby Stephenson  <[email protected]>
 
 	* Fixed bug with updating GUI after check-in entries.
diff --git a/src/fetch/upcitemdbfetcher.cpp b/src/fetch/upcitemdbfetcher.cpp
index 77c04e476..d4eeae3f5 100644
--- a/src/fetch/upcitemdbfetcher.cpp
+++ b/src/fetch/upcitemdbfetcher.cpp
@@ -92,7 +92,16 @@ void UPCItemDbFetcher::search() {
 
 void UPCItemDbFetcher::continueSearch() {
   m_started = true;
+  const auto searchTerms = FieldFormat::splitValue(request().value());
+  for(const auto& searchTerm : searchTerms) {
+    doSearch(searchTerm);
+  }
+  if(m_jobs.isEmpty()) {
+    stop();
+  }
+}
 
+void UPCItemDbFetcher::doSearch(const QString& term_) {
   QUrl u(QString::fromLatin1(UPCITEMDB_API_URL));
   u = u.adjusted(QUrl::StripTrailingSlash);
   u.setPath(u.path() + QLatin1String("/lookup"));
@@ -101,16 +110,14 @@ void UPCItemDbFetcher::continueSearch() {
     case ISBN:
       // do a upc search by 13-digit isbn
       {
-        // only grab first value
-        QString isbn = request().value().section(QLatin1Char(';'), 0);
-        isbn = ISBNValidator::isbn13(isbn);
+        QString isbn = ISBNValidator::isbn13(term_);
         isbn.remove(QLatin1Char('-'));
         q.addQueryItem(QStringLiteral("upc"), isbn);
       }
       break;
 
     case UPC:
-      q.addQueryItem(QStringLiteral("upc"), request().value());
+      q.addQueryItem(QStringLiteral("upc"), term_);
       break;
 
     default:
@@ -121,19 +128,29 @@ void UPCItemDbFetcher::continueSearch() {
   u.setQuery(q);
 
   myLog() << "Reading" << u.toDisplayString();
-  m_job = KIO::storedGet(u, KIO::NoReload, KIO::HideProgressInfo);
-  KJobWidgets::setWindow(m_job, GUI::Proxy::widget());
-  connect(m_job.data(), &KJob::result, this, &UPCItemDbFetcher::slotComplete);
+  QPointer<KIO::StoredTransferJob> job = KIO::storedGet(u, KIO::NoReload, KIO::HideProgressInfo);
+  KJobWidgets::setWindow(job, GUI::Proxy::widget());
+  connect(job.data(), &KJob::result, this, &UPCItemDbFetcher::slotComplete);
+  m_jobs << job;
+}
+
+void UPCItemDbFetcher::endJob(KIO::StoredTransferJob* job_) {
+  m_jobs.removeOne(job_);
+  if(m_jobs.isEmpty())  {
+    stop();
+  }
 }
 
 void UPCItemDbFetcher::stop() {
   if(!m_started) {
     return;
   }
-  if(m_job) {
-    m_job->kill();
-    m_job = nullptr;
+  for(auto& job : std::as_const(m_jobs)) {
+    if(job) {
+      job->kill();
+    }
   }
+  m_jobs.clear();
   m_started = false;
   Q_EMIT signalDone(this);
 }
@@ -162,19 +179,16 @@ void UPCItemDbFetcher::slotComplete(KJob* job_) {
 
   if(job->error()) {
     job->uiDelegate()->showErrorMessage();
-    stop();
+    endJob(job);
     return;
   }
 
   const QByteArray data = job->data();
   if(data.isEmpty()) {
     myDebug() << "No data";
-    stop();
+    endJob(job);
     return;
   }
-  // see bug 319662. If fetcher is cancelled, job is killed
-  // if the pointer is retained, it gets double-deleted
-  m_job = nullptr;
 
 #if 0
   myWarning() << "Remove debug from upcitemdbfetcher.cpp";
@@ -189,7 +203,7 @@ void UPCItemDbFetcher::slotComplete(KJob* job_) {
   QJsonDocument doc = QJsonDocument::fromJson(data);
   if(doc.isNull()) {
     myDebug() << "null JSON document";
-    stop();
+    endJob(job);
     return;
   }
   const auto obj = doc.object();
@@ -198,13 +212,13 @@ void UPCItemDbFetcher::slotComplete(KJob* job_) {
     const auto msg = objValue(obj, "message");
     message(msg, MessageHandler::Error);
     myDebug() << "UPCItemDbFetcher -" << msg;
-    stop();
+    endJob(job);
     return;
   }
 
   Data::CollPtr coll = CollectionFactory::collection(collectionType(), true);
   if(!coll) {
-    stop();
+    endJob(job);
     return;
   }
 
@@ -217,7 +231,7 @@ void UPCItemDbFetcher::slotComplete(KJob* job_) {
   const auto results = obj.value(QLatin1StringView("items")).toArray();
   if(results.isEmpty()) {
     myLog() << "No results";
-    stop();
+    endJob(job);
     return;
   }
 
@@ -237,7 +251,7 @@ void UPCItemDbFetcher::slotComplete(KJob* job_) {
     }
   }
 
-  stop();
+  endJob(job);
 }
 
 Tellico::Data::EntryPtr UPCItemDbFetcher::fetchEntryHook(uint uid_) {
diff --git a/src/fetch/upcitemdbfetcher.h b/src/fetch/upcitemdbfetcher.h
index 5eddc795c..977a4e023 100644
--- a/src/fetch/upcitemdbfetcher.h
+++ b/src/fetch/upcitemdbfetcher.h
@@ -91,6 +91,8 @@ private Q_SLOTS:
 private:
   virtual void search() override;
   virtual FetchRequest updateRequest(Data::EntryPtr entry) override;
+  void doSearch(const QString& term);
+  void endJob(KIO::StoredTransferJob* job);
   void populateEntry(Data::EntryPtr entry, const QJsonObject& obj);
   void parseTitle(Data::EntryPtr entry);
   bool parseTitleToken(Data::EntryPtr entry, const QString& token);
@@ -98,7 +100,7 @@ private:
   bool m_started;
 
   QHash<uint, Data::EntryPtr> m_entries;
-  QPointer<KIO::StoredTransferJob> m_job;
+  QList< QPointer<KIO::StoredTransferJob> > m_jobs;
 };
 
   } // end namespace
diff --git a/src/tests/upcitemdbfetchertest.cpp b/src/tests/upcitemdbfetchertest.cpp
index fe499940c..6e9d00b03 100644
--- a/src/tests/upcitemdbfetchertest.cpp
+++ b/src/tests/upcitemdbfetchertest.cpp
@@ -164,3 +164,16 @@ void UPCItemDbFetcherTest::testGTA4() {
 //  QVERIFY(!entry->field(QStringLiteral("cover")).contains(QLatin1Char('/')));
   QVERIFY(!entry->field(QStringLiteral("description")).isEmpty());
 }
+
+void UPCItemDbFetcherTest::testMultiple() {
+  Tellico::Fetch::FetchRequest request(Tellico::Data::Collection::Video, Tellico::Fetch::UPC,
+                                       QStringLiteral("024543617907; 024543781080"));
+  Tellico::Fetch::Fetcher::Ptr fetcher(new Tellico::Fetch::UPCItemDbFetcher(this));
+
+  Tellico::Data::EntryList results = DO_FETCH(fetcher, request);
+
+  QCOMPARE(results.size(), 2);
+
+  Tellico::Data::EntryPtr entry = results.at(0);
+  QVERIFY(entry);
+}
diff --git a/src/tests/upcitemdbfetchertest.h b/src/tests/upcitemdbfetchertest.h
index 897df712c..1f09dea80 100644
--- a/src/tests/upcitemdbfetchertest.h
+++ b/src/tests/upcitemdbfetchertest.h
@@ -39,6 +39,7 @@ private Q_SLOTS:
   void test1632();
   void testBurningEdge();
   void testGTA4();
+  void testMultiple();
 };
 
 #endif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.