From 0f07fc3153b23bb0f06c64b50b9bf1c28c088de9 Mon Sep 17 00:00:00 2001 From: Timmy Welch Date: Sun, 3 Sep 2023 15:18:56 -0700 Subject: [PATCH] Use a dictionary instead of a list in the issue/series selection windows List lookups were done by row number which became inaccurate if any sorting was done Fixes #507 --- comictaggerlib/issueselectionwindow.py | 12 ++--- comictaggerlib/seriesselectionwindow.py | 60 +++++++++++++------------ 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/comictaggerlib/issueselectionwindow.py b/comictaggerlib/issueselectionwindow.py index a63fe40..0c8f9ea 100644 --- a/comictaggerlib/issueselectionwindow.py +++ b/comictaggerlib/issueselectionwindow.py @@ -87,7 +87,7 @@ class IssueSelectionWindow(QtWidgets.QDialog): self.config = config self.talker = talker self.url_fetch_thread = None - self.issue_list: list[GenericMetadata] = [] + self.issue_list: dict[str, GenericMetadata] = {} # Display talker logo and set url self.lblIssuesSourceName.setText(talker.attribution) @@ -143,7 +143,9 @@ class IssueSelectionWindow(QtWidgets.QDialog): QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WaitCursor)) try: - self.issue_list = self.talker.fetch_issues_in_series(self.series_id) + self.issue_list = { + x.issue_id: x for x in self.talker.fetch_issues_in_series(self.series_id) if x.issue_id is not None + } except TalkerError as e: QtWidgets.QApplication.restoreOverrideCursor() QtWidgets.QMessageBox.critical(self, f"{e.source} {e.code_name} Error", f"{e}") @@ -153,7 +155,7 @@ class IssueSelectionWindow(QtWidgets.QDialog): self.twList.setSortingEnabled(False) - for row, issue in enumerate(self.issue_list): + for row, issue in enumerate(self.issue_list.values()): self.twList.insertRow(row) item_text = issue.issue or "" @@ -208,8 +210,8 @@ class IssueSelectionWindow(QtWidgets.QDialog): self.issue_id = self.twList.item(curr.row(), 0).data(QtCore.Qt.ItemDataRole.UserRole) # list selection was changed, update the the issue cover - issue = self.issue_list[curr.row()] - if not all((issue.issue, issue.year, issue.month, issue.cover_image)): # issue.title, issue.description + issue = self.issue_list[self.issue_id] + if not (issue.issue and issue.year and issue.month and issue.cover_image): issue = self.talker.fetch_comic_data(issue_id=self.issue_id) self.issue_number = issue.issue or "" self.coverWidget.set_issue_details(self.issue_id, [issue.cover_image or "", *issue.alternate_images]) diff --git a/comictaggerlib/seriesselectionwindow.py b/comictaggerlib/seriesselectionwindow.py index 2e8e467..2f3e282 100644 --- a/comictaggerlib/seriesselectionwindow.py +++ b/comictaggerlib/seriesselectionwindow.py @@ -153,7 +153,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): self.comic_archive = comic_archive self.immediate_autoselect = autoselect self.cover_index_list = cover_index_list - self.series_list: list[ComicSeries] = [] + self.series_list: dict[str, ComicSeries] = {} self.literal = literal self.ii: IssueIdentifier | None = None self.iddialog: IDProgressWindow | None = None @@ -332,7 +332,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): def show_issues(self) -> None: selector = IssueSelectionWindow(self, self.config, self.talker, self.series_id, self.issue_number) title = "" - for series in self.series_list: + for series in self.series_list.values(): if series.id == self.series_id: title = f"{series.name} ({series.start_year:04}) - " break @@ -349,8 +349,8 @@ class SeriesSelectionWindow(QtWidgets.QDialog): self.imageWidget.update_content() def select_by_id(self) -> None: - for r, series in enumerate(self.series_list): - if series.id == self.series_id: + for r in range(self.twList.rows()): + if self.series_id == self.twList.item(r, 0).data(QtCore.Qt.ItemDataRole.UserRole): self.twList.selectRow(r) break @@ -404,16 +404,18 @@ class SeriesSelectionWindow(QtWidgets.QDialog): ) return - self.series_list = self.search_thread.ct_search_results if self.search_thread is not None else [] + tmp_list = self.search_thread.ct_search_results if self.search_thread is not None else [] + self.series_list = {x.id: x for x in tmp_list} # filter the publishers if enabled set if self.use_filter: try: publisher_filter = {s.strip().casefold() for s in self.config.identifier_publisher_filter} # use '' as publisher name if None - self.series_list = list( + self.series_list = dict( filter( - lambda d: ("" if d.publisher is None else str(d.publisher).casefold()) not in publisher_filter, - self.series_list, + lambda d: ("" if d[1].publisher is None else str(d[1].publisher).casefold()) + not in publisher_filter, + self.series_list.items(), ) ) except Exception: @@ -425,17 +427,19 @@ class SeriesSelectionWindow(QtWidgets.QDialog): # sort by start_year if set if self.config.identifier_sort_series_by_year: try: - self.series_list = natsort.natsorted( - self.series_list, - key=lambda i: (str(i.start_year), str(i.count_of_issues)), - reverse=True, + self.series_list = dict( + natsort.natsorted( + self.series_list.items(), + key=lambda i: (str(i[1].start_year), str(i[1].count_of_issues)), + reverse=True, + ) ) except Exception: logger.exception("bad data error sorting results by start_year,count_of_issues") else: try: - self.series_list = natsort.natsorted( - self.series_list, key=lambda i: str(i.count_of_issues), reverse=True + self.series_list = dict( + natsort.natsorted(self.series_list.items(), key=lambda i: str(i[1].count_of_issues), reverse=True) ) except Exception: logger.exception("bad data error sorting results by count_of_issues") @@ -446,7 +450,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): sanitized = utils.sanitize_title(self.series_name, False).casefold() sanitized_no_articles = utils.sanitize_title(self.series_name, True).casefold() - deques: list[deque[ComicSeries]] = [deque(), deque(), deque()] + deques: list[deque[tuple[str, ComicSeries]]] = [deque(), deque(), deque()] def categorize(result: ComicSeries) -> int: # We don't remove anything on this one so that we only get exact matches @@ -458,10 +462,10 @@ class SeriesSelectionWindow(QtWidgets.QDialog): return 1 return 2 - for comic in self.series_list: - deques[categorize(comic)].append(comic) + for comic in self.series_list.items(): + deques[categorize(comic[1])].append(comic) logger.info("Length: %d, %d, %d", len(deques[0]), len(deques[1]), len(deques[2])) - self.series_list = list(itertools.chain.from_iterable(deques)) + self.series_list = dict(itertools.chain.from_iterable(deques)) except Exception: logger.exception("bad data error filtering exact/near matches") @@ -471,7 +475,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog): self.twList.setRowCount(0) - for row, series in enumerate(self.series_list): + for row, series in enumerate(self.series_list.values()): self.twList.insertRow(row) item_text = series.name @@ -553,16 +557,14 @@ class SeriesSelectionWindow(QtWidgets.QDialog): self.series_id = self.twList.item(curr.row(), 0).data(QtCore.Qt.ItemDataRole.UserRole) # list selection was changed, update the info on the series - series = self.series_list[curr.row()] - if not all( - ( - series.name, - series.start_year, - series.count_of_issues, - series.publisher, - series.description, - series.image_url, - ) + series = self.series_list[self.series_id] + if not ( + series.name + and series.start_year + and series.count_of_issues + and series.publisher + and series.description + and series.image_url ): series = self.talker.fetch_series(self.series_id) if series.description is None: