From 6cf71d12c8e41f31156b9e7ace684a56c9846129 Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Mon, 13 Aug 2018 17:24:55 -0600 Subject: [PATCH 1/5] Update coverart type acceptance logic --- picard/coverart/providers/caa.py | 86 ++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/picard/coverart/providers/caa.py b/picard/coverart/providers/caa.py index 20ad2bf6d..c71736602 100644 --- a/picard/coverart/providers/caa.py +++ b/picard/coverart/providers/caa.py @@ -95,11 +95,20 @@ def caa_url_fallback_list(desired_size, thumbnails): class CAATypesSelectorDialog(QtWidgets.QDialog): - _columns = 4 + _columns = 3 # Number of main display columns + _subcolumns = 3 # Number of columns comprising a main display column (i.e.: label, combobox, spacer) + _spacer_width = 35 # Width of the spacer columns in pixels - def __init__(self, parent=None, types=None): - if types is None: - types = [] + # Combo box index definitions + IDX_INCLUDE_TYPE = 0 + IDX_IGNORE_TYPE = 1 + IDX_EXCLUDE_TYPE = 2 + + def __init__(self, parent=None, types_include=None, types_exclude=None): + if types_include is None: + types_include = [] + if types_exclude is None: + types_exclude = [] super().__init__(parent) self.setWindowTitle(_("Cover art types")) @@ -108,15 +117,29 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): grid = QtWidgets.QWidget() gridlayout = QtWidgets.QGridLayout() + # Set up spacer columns between type selection columns + spacer_column_index = self._subcolumns - 1 # index of first spacer column + while spacer_column_index < self._columns * self._subcolumns - 1: + gridlayout.setColumnMinimumWidth(spacer_column_index, self._spacer_width) + spacer_column_index += self._subcolumns grid.setLayout(gridlayout) for index, caa_type in enumerate(CAA_TYPES): row = index // self._columns - column = index % self._columns + column = (index % self._columns) * self._subcolumns name = caa_type["name"] - text = translate_caa_type(name) - item = QtWidgets.QCheckBox(text) - item.setChecked(name in types) + item = QtWidgets.QLabel() + item.setText(translate_caa_type(name)) + gridlayout.addWidget(item, row, column) + column += 1 + item = QtWidgets.QComboBox() + item.addItems([ _('Include'), _('Ignore'), _('Exclude'),]) + if name in types_include: + item.setCurrentIndex(self.IDX_INCLUDE_TYPE) # Include coverart type + elif name in types_exclude: + item.setCurrentIndex(self.IDX_EXCLUDE_TYPE) # Exclude coverart type + else: + item.setCurrentIndex(self.IDX_IGNORE_TYPE) # Ignore coverart type self._items[item] = caa_type gridlayout.addWidget(item, row, column) @@ -132,8 +155,9 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): StandardButton(StandardButton.HELP), QtWidgets.QDialogButtonBox.HelpRole) extrabuttons = [ - (N_("Chec&k all"), self.checkall), - (N_("&Uncheck all"), self.uncheckall), + (N_("I&nclude all"), self.checkall), + (N_("E&xclude all"), self.uncheckall), + (N_("I&gnore all"), self.ignoreall), ] for label, callback in extrabuttons: button = QtWidgets.QPushButton(_(label)) @@ -152,26 +176,35 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): webbrowser2.goto('doc_cover_art_types') def uncheckall(self): - self._set_checked_all(False) + self._set_checked_all(2) def checkall(self): - self._set_checked_all(True) + self._set_checked_all(0) + + def ignoreall(self): + self._set_checked_all(1) def _set_checked_all(self, value): for item in self._items.keys(): - item.setChecked(value) + item.setCurrentIndex(value) - def get_selected_types(self): + def get_selected_types_include(self): return [typ['name'] for item, typ in self._items.items() if - item.isChecked()] or ['front'] + item.currentIndex() == self.IDX_INCLUDE_TYPE] or ['front'] + + def get_selected_types_exclude(self): + return [typ['name'] for item, typ in self._items.items() if + item.currentIndex() == self.IDX_EXCLUDE_TYPE] or ['none'] @staticmethod - def run(parent=None, types=None): - if types is None: - types = [] - dialog = CAATypesSelectorDialog(parent, types) + def run(parent=None, types_include=None, types_exclude=None): + if types_include is None: + types_include = [] + if types_exclude is None: + types_exclude = [] + dialog = CAATypesSelectorDialog(parent, types_include, types_exclude) result = dialog.exec_() - return (dialog.get_selected_types(), result == QtWidgets.QDialog.Accepted) + return (dialog.get_selected_types_include(), dialog.get_selected_types_exclude(), result == QtWidgets.QDialog.Accepted) class ProviderOptionsCaa(ProviderOptions): @@ -187,6 +220,7 @@ class ProviderOptionsCaa(ProviderOptions): _CAA_IMAGE_SIZE_DEFAULT), config.ListOption("setting", "caa_image_types", ["front"]), config.BoolOption("setting", "caa_restrict_image_types", True), + config.ListOption("setting", "caa_image_types_to_omit", ["raw/unedited"]), ] _options_ui = Ui_CaaOptions @@ -231,10 +265,11 @@ class ProviderOptionsCaa(ProviderOptions): self.ui.select_caa_types.setEnabled(enabled) def select_caa_types(self): - (types, ok) = CAATypesSelectorDialog.run( - self, config.setting["caa_image_types"]) + (types, types_to_omit, ok) = CAATypesSelectorDialog.run( + self, config.setting["caa_image_types"], config.setting["caa_image_types_to_omit"]) if ok: config.setting["caa_image_types"] = types + config.setting["caa_image_types_to_omit"] = types_to_omit @@ -253,6 +288,7 @@ class CoverArtProviderCaa(CoverArtProvider): def __init__(self, coverart): super().__init__(coverart) self.caa_types = list(map(str.lower, config.setting["caa_image_types"])) + self.caa_types_to_omit = list(map(str.lower, config.setting["caa_image_types_to_omit"])) self.len_caa_types = len(self.caa_types) self.restrict_types = config.setting["caa_restrict_image_types"] @@ -346,6 +382,8 @@ class CoverArtProviderCaa(CoverArtProvider): except ValueError: self.error("Invalid JSON: %s" % (http.url().toString())) else: + if self.restrict_types: + log.debug('CAA types: included: %s, excluded: %s' % (self.caa_types, self.caa_types_to_omit,)) for image in caa_data["images"]: if config.setting["caa_approved_only"] and not image["approved"]: continue @@ -364,6 +402,10 @@ class CoverArtProviderCaa(CoverArtProvider): # only keep enabled caa types types = set(image["types"]).intersection( set(self.caa_types)) + if types and self.caa_types_to_omit: + types = not set(image["types"]).intersection( + set(self.caa_types_to_omit)) + log.debug('CAA Image %s: %s %s' % ('accepted' if types else 'rejected', image['image'], image['types'],)) else: types = True if types: From 9970c6f4fb737ee25dcd54f372f1b21fddec88cd Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Fri, 17 Aug 2018 17:48:19 -0600 Subject: [PATCH 2/5] Use list boxes for coverart type selection - Sort lists and enable / disable buttons as appropriate - Allow multiple selections, and add button to reset to defaults. --- picard/coverart/providers/caa.py | 306 +++++++++++++++++++++++++------ 1 file changed, 255 insertions(+), 51 deletions(-) diff --git a/picard/coverart/providers/caa.py b/picard/coverart/providers/caa.py index c71736602..4c8d58a4c 100644 --- a/picard/coverart/providers/caa.py +++ b/picard/coverart/providers/caa.py @@ -72,6 +72,61 @@ _CAA_THUMBNAIL_SIZE_MAP = OrderedDict([ _CAA_IMAGE_SIZE_DEFAULT = 500 +_CAA_IMAGE_TYPE_DEFAULT_INCLUDE = [ 'front', ] +_CAA_IMAGE_TYPE_DEFAULT_EXCLUDE = [ 'raw/unedited', 'watermark', ] + + +def make_list_box(): + """Make standard list box for CAA image type selection dialog.""" + list_box = QtWidgets.QListWidget() + list_box.setFixedSize(QtCore.QSize(150, 250)) + list_box.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + list_box.setSortingEnabled(True) + list_box.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) + return list_box + +def make_arrow_button(label, command): + """Make standard arrow button for CAA image type selection dialog.""" + item = QtWidgets.QPushButton(label) + item.clicked.connect(command) + item.setFixedSize(QtCore.QSize(35, 20)) + return item + +def make_arrows_column(list_add, list_add_all, list_remove, list_remove_all, reverse=False): + """Make standard arrow buttons column for CAA image type selection dialog.""" + _spacer_item = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + arrows = QtWidgets.QWidget() + arrows_layout = QtWidgets.QVBoxLayout() + arrows.setLayout(arrows_layout) + arrows_layout.addItem(QtWidgets.QSpacerItem(_spacer_item)) + arrows_layout.addWidget(make_arrow_button('>' if reverse else '<', list_add)) + arrows_layout.addWidget(make_arrow_button('>>' if reverse else '<<', list_add_all)) + arrows_layout.addWidget(make_arrow_button('<' if reverse else '>', list_remove)) + arrows_layout.addWidget(make_arrow_button('<<' if reverse else '>>', list_remove_all)) + arrows_layout.addItem(QtWidgets.QSpacerItem(_spacer_item)) + return arrows + +def move_item(item, list1, list2): + """Move the specified item from one listbox to another. Used in the CAA image type selection dialog.""" + clone = item.clone() + list2.addItem(clone) + list1.takeItem(list1.row(item)) + +def move_selected_items(list1, list2): + """Move the selected item from one listbox to another. Used in the CAA image type selection dialog.""" + for item in list1.selectedItems(): + move_item(item, list1, list2) + +def move_all_items(list1, list2): + """Move all items from one listbox to another. Used in the CAA image type selection dialog.""" + while list1.count(): + item = list1.item(0) + move_item(item, list1, list2) + +def clear_listbox_focus(list_to_clear): + """Clear all item selections in the specified listbox.""" + list_to_clear.clearSelection() + def caa_url_fallback_list(desired_size, thumbnails): """List of thumbnail urls equal or smaller than size, in size decreasing order @@ -95,14 +150,15 @@ def caa_url_fallback_list(desired_size, thumbnails): class CAATypesSelectorDialog(QtWidgets.QDialog): - _columns = 3 # Number of main display columns - _subcolumns = 3 # Number of columns comprising a main display column (i.e.: label, combobox, spacer) - _spacer_width = 35 # Width of the spacer columns in pixels + """Display dialog box to select the CAA image types to include and exclude from download and use.""" - # Combo box index definitions - IDX_INCLUDE_TYPE = 0 - IDX_IGNORE_TYPE = 1 - IDX_EXCLUDE_TYPE = 2 + # Dictionary of standard image type names by translated image type title + # key: image type title displayed in list boxes (translated by i18n) + # value: standard image type name + # + # This is used to return the include and exclude lists containing standard image + # type names based on the titles displayed in the list boxes in the dialog. + image_types_by_display_title = {} def __init__(self, parent=None, types_include=None, types_exclude=None): if types_include is None: @@ -112,39 +168,81 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): super().__init__(parent) self.setWindowTitle(_("Cover art types")) - self._items = {} self.layout = QtWidgets.QVBoxLayout(self) + # Populate display title / standard name dictionary + for caa_type in CAA_TYPES: + name = caa_type['name'] + title = _(caa_type['title']) + self.image_types_by_display_title[title] = name + + # Create list boxes for dialog + self.list_include = make_list_box() + self.list_exclude = make_list_box() + self.list_ignore = make_list_box() + + # Populate list boxes from current settings + self.fill_lists(types_include, types_exclude) + + self.list_include.clicked.connect(self.focus_set_include) + self.list_exclude.clicked.connect(self.focus_set_exclude) + self.list_ignore.clicked.connect(self.focus_set_ignore) + + # Add instructions to the dialog box + instructions = QtWidgets.QLabel() + instructions.setText(_("Please select the contents of the image type 'Include' and 'Exclude' lists.")) + instructions.setWordWrap(True) + instructions.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + self.layout.addWidget(instructions) + grid = QtWidgets.QWidget() gridlayout = QtWidgets.QGridLayout() - # Set up spacer columns between type selection columns - spacer_column_index = self._subcolumns - 1 # index of first spacer column - while spacer_column_index < self._columns * self._subcolumns - 1: - gridlayout.setColumnMinimumWidth(spacer_column_index, self._spacer_width) - spacer_column_index += self._subcolumns grid.setLayout(gridlayout) - for index, caa_type in enumerate(CAA_TYPES): - row = index // self._columns - column = (index % self._columns) * self._subcolumns - name = caa_type["name"] - item = QtWidgets.QLabel() - item.setText(translate_caa_type(name)) - gridlayout.addWidget(item, row, column) - column += 1 - item = QtWidgets.QComboBox() - item.addItems([ _('Include'), _('Ignore'), _('Exclude'),]) - if name in types_include: - item.setCurrentIndex(self.IDX_INCLUDE_TYPE) # Include coverart type - elif name in types_exclude: - item.setCurrentIndex(self.IDX_EXCLUDE_TYPE) # Exclude coverart type - else: - item.setCurrentIndex(self.IDX_IGNORE_TYPE) # Ignore coverart type - self._items[item] = caa_type - gridlayout.addWidget(item, row, column) + row = 0 + column = 0 + item = QtWidgets.QLabel() + item.setText(_("Include types list")) + gridlayout.addWidget(item, row, column) + + column = 4 + item = QtWidgets.QLabel() + item.setText(_("Exclude types list")) + gridlayout.addWidget(item, row, column) + + row = 1 + column = 0 + gridlayout.addWidget(self.list_include, row, column) + + column = 1 + self.arrows_include = make_arrows_column(self.add_include, self.add_include_all, self.remove_include, self.remove_include_all) + gridlayout.addWidget(self.arrows_include, row, column) + + column = 2 + gridlayout.addWidget(self.list_ignore, row, column) + + column = 3 + self.arrows_exclude = make_arrows_column(self.add_exclude, self.add_exclude_all, self.remove_exclude, self.remove_exclude_all, reverse=True) + gridlayout.addWidget(self.arrows_exclude, row, column) + + column = 4 + gridlayout.addWidget(self.list_exclude, row, column) self.layout.addWidget(grid) + # Add usage explanation to the dialog box + instructions = QtWidgets.QLabel() + instructions.setText(_( + "CAA images with an image type found in the 'Include' list will be downloaded and used " + "UNLESS they also have an image type found in the 'Exclude' list. Images with types " + "found in the 'Exclude' list will NEVER be used. Image types not appearing in the 'Include' " + "or 'Exclude' lists will not be considered when determining whether or not to download and " + "use a CAA image.\n") + ) + instructions.setWordWrap(True) + instructions.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + self.layout.addWidget(instructions) + self.buttonbox = QtWidgets.QDialogButtonBox(self) self.buttonbox.setOrientation(QtCore.Qt.Horizontal) self.buttonbox.addButton( @@ -155,12 +253,13 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): StandardButton(StandardButton.HELP), QtWidgets.QDialogButtonBox.HelpRole) extrabuttons = [ - (N_("I&nclude all"), self.checkall), - (N_("E&xclude all"), self.uncheckall), - (N_("I&gnore all"), self.ignoreall), + (N_("I&nclude all"), self.include_all), + (N_("E&xclude all"), self.exclude_all), + (N_("C&lear all"), self.clear_all), + (N_("Restore &Defaults"), self.reset_to_defaults), ] for label, callback in extrabuttons: - button = QtWidgets.QPushButton(_(label)) + button = QtWidgets.QPushButton(label) button.setSizePolicy( QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding) self.buttonbox.addButton(button, QtWidgets.QDialogButtonBox.ActionRole) @@ -172,29 +271,134 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): self.buttonbox.rejected.connect(self.reject) self.buttonbox.helpRequested.connect(self.help) + self.fix_buttons() + + def fill_lists(self, includes, excludes): + """Fill dialog listboxes. + + First clears the contents of the three listboxes, and then populates the listboxes + from the dictionary of translated standard CAA types, using the provided 'includes' + and 'excludes' lists to determine the appropriate list for each type. + + Arguments: + includes -- list of standard image types to place in the "Include" listbox + excludes -- list of standard image types to place in the "Exclude" listbox + """ + self.list_include.clear() + self.list_exclude.clear() + self.list_ignore.clear() + for title in self.image_types_by_display_title: + name = self.image_types_by_display_title[title] + if name in includes: + self.list_include.addItem(title) + elif name in excludes: + self.list_exclude.addItem(title) + else: + self.list_ignore.addItem(title) + def help(self): webbrowser2.goto('doc_cover_art_types') - def uncheckall(self): - self._set_checked_all(2) + def add_include(self): + move_selected_items(self.list_ignore, self.list_include) + self.fix_buttons() - def checkall(self): - self._set_checked_all(0) + def remove_include(self): + move_selected_items(self.list_include, self.list_ignore) + self.fix_buttons() - def ignoreall(self): - self._set_checked_all(1) + def add_include_all(self): + move_all_items(self.list_ignore, self.list_include) + self.fix_buttons() - def _set_checked_all(self, value): - for item in self._items.keys(): - item.setCurrentIndex(value) + def remove_include_all(self): + move_all_items(self.list_include, self.list_ignore) + self.fix_buttons() + + def add_exclude(self): + move_selected_items(self.list_ignore, self.list_exclude) + self.fix_buttons() + + def remove_exclude(self): + move_selected_items(self.list_exclude, self.list_ignore) + self.fix_buttons() + + def add_exclude_all(self): + move_all_items(self.list_ignore, self.list_exclude) + self.fix_buttons() + + def remove_exclude_all(self): + move_all_items(self.list_exclude, self.list_ignore) + self.fix_buttons() + + def include_all(self): + move_all_items(self.list_ignore, self.list_include) + move_all_items(self.list_exclude, self.list_include) + self.fix_buttons() + + def exclude_all(self): + move_all_items(self.list_ignore, self.list_exclude) + move_all_items(self.list_include, self.list_exclude) + self.fix_buttons() + + def clear_all(self): + move_all_items(self.list_include, self.list_ignore) + move_all_items(self.list_exclude, self.list_ignore) + self.fix_buttons() def get_selected_types_include(self): - return [typ['name'] for item, typ in self._items.items() if - item.currentIndex() == self.IDX_INCLUDE_TYPE] or ['front'] + return [self.image_types_by_display_title[self.list_include.item(index).text()] for index in range(self.list_include.count())] or ['front'] def get_selected_types_exclude(self): - return [typ['name'] for item, typ in self._items.items() if - item.currentIndex() == self.IDX_EXCLUDE_TYPE] or ['none'] + return [self.image_types_by_display_title[self.list_exclude.item(index).text()] for index in range(self.list_exclude.count())] or ['none'] + + def focus_set_include(self): + clear_listbox_focus(self.list_exclude) + clear_listbox_focus(self.list_ignore) + self.fix_buttons() + + def focus_set_exclude(self): + clear_listbox_focus(self.list_include) + clear_listbox_focus(self.list_ignore) + self.fix_buttons() + + def focus_set_ignore(self): + clear_listbox_focus(self.list_include) + clear_listbox_focus(self.list_exclude) + self.fix_buttons() + + def focus_clear_all(self): + clear_listbox_focus(self.list_include) + clear_listbox_focus(self.list_exclude) + clear_listbox_focus(self.list_ignore) + self.fix_buttons() + + def reset_to_defaults(self): + self.fill_lists(_CAA_IMAGE_TYPE_DEFAULT_INCLUDE, _CAA_IMAGE_TYPE_DEFAULT_EXCLUDE) + self.fix_buttons() + + def fix_buttons(self): + has_items_include = self.list_include.count() + has_items_exclude = self.list_exclude.count() + has_items_ignore = self.list_ignore.count() + + has_selected_include = True if self.list_include.selectedItems() else False + has_selected_exclude = True if self.list_exclude.selectedItems() else False + has_selected_ignore = True if self.list_ignore.selectedItems() else False + + # "Include" list buttons + buttons = self.arrows_include.findChildren(QtWidgets.QPushButton) + buttons[0].setEnabled(has_items_ignore and has_selected_ignore) # '<' + buttons[1].setEnabled(has_items_ignore) # '<<' + buttons[2].setEnabled(has_items_include and has_selected_include) # '>' + buttons[3].setEnabled(has_items_include) # '>>' + + # "Exclude" list buttons + buttons = self.arrows_exclude.findChildren(QtWidgets.QPushButton) + buttons[0].setEnabled(has_items_ignore and has_selected_ignore) # '>' + buttons[1].setEnabled(has_items_ignore) # '>>' + buttons[2].setEnabled(has_items_exclude and has_selected_exclude) # '<' + buttons[3].setEnabled(has_items_exclude) # '<<' @staticmethod def run(parent=None, types_include=None, types_exclude=None): @@ -218,9 +422,9 @@ class ProviderOptionsCaa(ProviderOptions): config.BoolOption("setting", "caa_image_type_as_filename", False), config.IntOption("setting", "caa_image_size", _CAA_IMAGE_SIZE_DEFAULT), - config.ListOption("setting", "caa_image_types", ["front"]), + config.ListOption("setting", "caa_image_types", _CAA_IMAGE_TYPE_DEFAULT_INCLUDE), config.BoolOption("setting", "caa_restrict_image_types", True), - config.ListOption("setting", "caa_image_types_to_omit", ["raw/unedited"]), + config.ListOption("setting", "caa_image_types_to_omit", _CAA_IMAGE_TYPE_DEFAULT_EXCLUDE), ] _options_ui = Ui_CaaOptions @@ -405,7 +609,7 @@ class CoverArtProviderCaa(CoverArtProvider): if types and self.caa_types_to_omit: types = not set(image["types"]).intersection( set(self.caa_types_to_omit)) - log.debug('CAA Image %s: %s %s' % ('accepted' if types else 'rejected', image['image'], image['types'],)) + log.debug('CAA image %s: %s %s' % ('accepted' if types else 'rejected', image['image'], image['types'],)) else: types = True if types: From 259e176144c10fd82e662591849ec6ba698ad4b1 Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Mon, 20 Aug 2018 16:33:57 -0600 Subject: [PATCH 3/5] Use classes for list_box, arrow_button and arrows_column - Store image type name in listbox item for direct retrieval rather than retrieving it from a translated image type title dictionary. - Remove the no longer used translated image type title dictionary. - Rename the 'fix_buttons' method to 'set_buttons_enabled_state'. - Add callback to ArrowColumn methods to enable setting the enabled state of the buttons after moving items between lists. - Clean up logic around checking if lists have selected items. - Move arrow button commands to ArrowColumn class. --- picard/coverart/providers/caa.py | 381 ++++++++++++++++--------------- 1 file changed, 192 insertions(+), 189 deletions(-) diff --git a/picard/coverart/providers/caa.py b/picard/coverart/providers/caa.py index 4c8d58a4c..a7fbc57f5 100644 --- a/picard/coverart/providers/caa.py +++ b/picard/coverart/providers/caa.py @@ -26,8 +26,10 @@ from collections import ( OrderedDict, namedtuple, ) +from functools import partial from PyQt5 import ( + Qt, QtCore, QtWidgets, ) @@ -72,60 +74,8 @@ _CAA_THUMBNAIL_SIZE_MAP = OrderedDict([ _CAA_IMAGE_SIZE_DEFAULT = 500 -_CAA_IMAGE_TYPE_DEFAULT_INCLUDE = [ 'front', ] -_CAA_IMAGE_TYPE_DEFAULT_EXCLUDE = [ 'raw/unedited', 'watermark', ] - - -def make_list_box(): - """Make standard list box for CAA image type selection dialog.""" - list_box = QtWidgets.QListWidget() - list_box.setFixedSize(QtCore.QSize(150, 250)) - list_box.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - list_box.setSortingEnabled(True) - list_box.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) - return list_box - -def make_arrow_button(label, command): - """Make standard arrow button for CAA image type selection dialog.""" - item = QtWidgets.QPushButton(label) - item.clicked.connect(command) - item.setFixedSize(QtCore.QSize(35, 20)) - return item - -def make_arrows_column(list_add, list_add_all, list_remove, list_remove_all, reverse=False): - """Make standard arrow buttons column for CAA image type selection dialog.""" - _spacer_item = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - arrows = QtWidgets.QWidget() - arrows_layout = QtWidgets.QVBoxLayout() - arrows.setLayout(arrows_layout) - arrows_layout.addItem(QtWidgets.QSpacerItem(_spacer_item)) - arrows_layout.addWidget(make_arrow_button('>' if reverse else '<', list_add)) - arrows_layout.addWidget(make_arrow_button('>>' if reverse else '<<', list_add_all)) - arrows_layout.addWidget(make_arrow_button('<' if reverse else '>', list_remove)) - arrows_layout.addWidget(make_arrow_button('<<' if reverse else '>>', list_remove_all)) - arrows_layout.addItem(QtWidgets.QSpacerItem(_spacer_item)) - return arrows - -def move_item(item, list1, list2): - """Move the specified item from one listbox to another. Used in the CAA image type selection dialog.""" - clone = item.clone() - list2.addItem(clone) - list1.takeItem(list1.row(item)) - -def move_selected_items(list1, list2): - """Move the selected item from one listbox to another. Used in the CAA image type selection dialog.""" - for item in list1.selectedItems(): - move_item(item, list1, list2) - -def move_all_items(list1, list2): - """Move all items from one listbox to another. Used in the CAA image type selection dialog.""" - while list1.count(): - item = list1.item(0) - move_item(item, list1, list2) - -def clear_listbox_focus(list_to_clear): - """Clear all item selections in the specified listbox.""" - list_to_clear.clearSelection() +_CAA_IMAGE_TYPE_DEFAULT_INCLUDE = ['front',] +_CAA_IMAGE_TYPE_DEFAULT_EXCLUDE = ['raw/unedited', 'watermark',] def caa_url_fallback_list(desired_size, thumbnails): @@ -149,44 +99,138 @@ def caa_url_fallback_list(desired_size, thumbnails): return urls -class CAATypesSelectorDialog(QtWidgets.QDialog): - """Display dialog box to select the CAA image types to include and exclude from download and use.""" +class ArrowButton(QtWidgets.QPushButton): + """Standard arrow button for CAA image type selection dialog. - # Dictionary of standard image type names by translated image type title - # key: image type title displayed in list boxes (translated by i18n) - # value: standard image type name - # - # This is used to return the include and exclude lists containing standard image - # type names based on the titles displayed in the list boxes in the dialog. - image_types_by_display_title = {} + Keyword Arguments: + label {string} -- Label to display on the button + command {command} -- Command to execute when the button is clicked (default: {None}) + parent {[type]} -- Parent of the QPushButton object being created (default: {None}) + """ + + ARROW_BUTTON_WIDTH = 35 + ARROW_BUTTON_HEIGHT = 20 + + def __init__(self, label, command=None, parent=None): + if label is None: + label = '.' + super().__init__(label, parent=parent) + if command is not None: + self.clicked.connect(command) + self.setFixedSize(QtCore.QSize(self.ARROW_BUTTON_WIDTH, self.ARROW_BUTTON_HEIGHT)) + + +class ArrowsColumn(QtWidgets.QWidget): + """Standard arrow buttons column for CAA image type selection dialog. + + Keyword Arguments: + selection_list {ListBox} -- ListBox of selected items associated with this arrow column + ignore_list {ListBox} -- ListBox of unselected items associated with this arrow column + callback {command} -- Command to execute after items are moved between lists (default: {None}) + reverse {bool} -- Determines whether the arrow directions should be reversed (default: {False}) + parent {[type]} -- Parent of the QWidget object being created (default: {None}) + """ + + def __init__(self, selection_list, ignore_list, callback=None, reverse=False, parent=None): + super().__init__(parent=parent) + self.selection_list = selection_list + self.ignore_list = ignore_list + self.callback = callback + spacer_item = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + arrows_layout = QtWidgets.QVBoxLayout() + arrows_layout.addItem(QtWidgets.QSpacerItem(spacer_item)) + self.button_add = ArrowButton('>' if reverse else '<', self.move_from_ignore) + arrows_layout.addWidget(self.button_add) + self.button_add_all = ArrowButton('>>' if reverse else '<<', self.move_all_from_ignore) + arrows_layout.addWidget(self.button_add_all) + self.button_remove = ArrowButton('<' if reverse else '>', self.move_to_ignore) + arrows_layout.addWidget(self.button_remove) + self.button_remove_all = ArrowButton('<<' if reverse else '>>', self.move_all_to_ignore) + arrows_layout.addWidget(self.button_remove_all) + arrows_layout.addItem(QtWidgets.QSpacerItem(spacer_item)) + self.setLayout(arrows_layout) + + def move_from_ignore(self): + self.ignore_list.move_selected_items(self.selection_list, callback=self.callback) + + def move_all_from_ignore(self): + self.ignore_list.move_all_items(self.selection_list, callback=self.callback) + + def move_to_ignore(self): + self.selection_list.move_selected_items(self.ignore_list, callback=self.callback) + + def move_all_to_ignore(self): + self.selection_list.move_all_items(self.ignore_list, callback=self.callback) + + +class ListBox(QtWidgets.QListWidget): + """Standard list box for CAA image type selection dialog. + + Keyword Arguments: + parent {[type]} -- Parent of the QListWidget object being created (default: {None}) + """ + + LISTBOX_WIDTH = 150 + LISTBOX_HEIGHT = 250 + + def __init__(self, parent=None): + super().__init__(parent=parent) + self.setFixedSize(QtCore.QSize(self.LISTBOX_WIDTH, self.LISTBOX_HEIGHT)) + self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.setSortingEnabled(True) + self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) + + def move_item(self, item, target_list): + """Move the specified item to another listbox.""" + self.takeItem(self.row(item)) + target_list.addItem(item) + + def move_selected_items(self, target_list, callback=None): + """Move the selected item to another listbox.""" + for item in self.selectedItems(): + self.move_item(item, target_list) + if callback: + callback() + + def move_all_items(self, target_list, callback=None): + """Move all items to another listbox.""" + while self.count(): + self.move_item(self.item(0), target_list) + if callback: + callback() + + +class CAATypesSelectorDialog(QtWidgets.QDialog): + """Display dialog box to select the CAA image types to include and exclude from download and use. + + Keyword Arguments: + parent {[type]} -- Parent of the QDialog object being created (default: {None}) + types_include {[string]} -- List of CAA image types to include (default: {None}) + types_exclude {[string]} -- List of CAA image types to exclude (default: {None}) + """ def __init__(self, parent=None, types_include=None, types_exclude=None): + super().__init__(parent) if types_include is None: types_include = [] if types_exclude is None: types_exclude = [] - super().__init__(parent) self.setWindowTitle(_("Cover art types")) self.layout = QtWidgets.QVBoxLayout(self) - # Populate display title / standard name dictionary - for caa_type in CAA_TYPES: - name = caa_type['name'] - title = _(caa_type['title']) - self.image_types_by_display_title[title] = name - # Create list boxes for dialog - self.list_include = make_list_box() - self.list_exclude = make_list_box() - self.list_ignore = make_list_box() + self.list_include = ListBox() + self.list_exclude = ListBox() + self.list_ignore = ListBox() # Populate list boxes from current settings self.fill_lists(types_include, types_exclude) - self.list_include.clicked.connect(self.focus_set_include) - self.list_exclude.clicked.connect(self.focus_set_exclude) - self.list_ignore.clicked.connect(self.focus_set_ignore) + # Set triggers when the lists receive the current focus + self.list_include.clicked.connect(partial(self.clear_focus, [self.list_ignore, self.list_exclude,])) + self.list_exclude.clicked.connect(partial(self.clear_focus, [self.list_ignore, self.list_include,])) + self.list_ignore.clicked.connect(partial(self.clear_focus, [self.list_include, self.list_exclude,])) # Add instructions to the dialog box instructions = QtWidgets.QLabel() @@ -215,14 +259,23 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): gridlayout.addWidget(self.list_include, row, column) column = 1 - self.arrows_include = make_arrows_column(self.add_include, self.add_include_all, self.remove_include, self.remove_include_all) + self.arrows_include = ArrowsColumn( + self.list_include, + self.list_ignore, + callback=self.set_buttons_enabled_state, + ) gridlayout.addWidget(self.arrows_include, row, column) column = 2 gridlayout.addWidget(self.list_ignore, row, column) column = 3 - self.arrows_exclude = make_arrows_column(self.add_exclude, self.add_exclude_all, self.remove_exclude, self.remove_exclude_all, reverse=True) + self.arrows_exclude = ArrowsColumn( + self.list_exclude, + self.list_ignore, + callback=self.set_buttons_enabled_state, + reverse=True + ) gridlayout.addWidget(self.arrows_exclude, row, column) column = 4 @@ -253,13 +306,13 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): StandardButton(StandardButton.HELP), QtWidgets.QDialogButtonBox.HelpRole) extrabuttons = [ - (N_("I&nclude all"), self.include_all), - (N_("E&xclude all"), self.exclude_all), - (N_("C&lear all"), self.clear_all), + (N_("I&nclude all"), self.move_all_to_include_list), + (N_("E&xclude all"), self.move_all_to_exclude_list), + (N_("C&lear all"), self.move_all_to_ignore_list), (N_("Restore &Defaults"), self.reset_to_defaults), ] for label, callback in extrabuttons: - button = QtWidgets.QPushButton(label) + button = QtWidgets.QPushButton(_(label)) button.setSizePolicy( QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding) self.buttonbox.addButton(button, QtWidgets.QDialogButtonBox.ActionRole) @@ -271,14 +324,29 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): self.buttonbox.rejected.connect(self.reject) self.buttonbox.helpRequested.connect(self.help) - self.fix_buttons() + self.set_buttons_enabled_state() + + def move_all_to_include_list(self): + self.list_ignore.move_all_items(self.list_include) + self.list_exclude.move_all_items(self.list_include) + self.set_buttons_enabled_state() + + def move_all_to_exclude_list(self): + self.list_ignore.move_all_items(self.list_exclude) + self.list_include.move_all_items(self.list_exclude) + self.set_buttons_enabled_state() + + def move_all_to_ignore_list(self): + self.list_include.move_all_items(self.list_ignore) + self.list_exclude.move_all_items(self.list_ignore) + self.set_buttons_enabled_state() def fill_lists(self, includes, excludes): """Fill dialog listboxes. First clears the contents of the three listboxes, and then populates the listboxes - from the dictionary of translated standard CAA types, using the provided 'includes' - and 'excludes' lists to determine the appropriate list for each type. + from the dictionary of standard CAA types, using the provided 'includes' and + 'excludes' lists to determine the appropriate list for each type. Arguments: includes -- list of standard image types to place in the "Include" listbox @@ -287,118 +355,56 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): self.list_include.clear() self.list_exclude.clear() self.list_ignore.clear() - for title in self.image_types_by_display_title: - name = self.image_types_by_display_title[title] + for caa_type in CAA_TYPES: + name = caa_type['name'] + title = translate_caa_type(caa_type['title']) + item = Qt.QListWidgetItem(title) + item.setData(QtCore.Qt.UserRole, name) if name in includes: - self.list_include.addItem(title) + self.list_include.addItem(item) elif name in excludes: - self.list_exclude.addItem(title) + self.list_exclude.addItem(item) else: - self.list_ignore.addItem(title) + self.list_ignore.addItem(item) def help(self): webbrowser2.goto('doc_cover_art_types') - def add_include(self): - move_selected_items(self.list_ignore, self.list_include) - self.fix_buttons() - - def remove_include(self): - move_selected_items(self.list_include, self.list_ignore) - self.fix_buttons() - - def add_include_all(self): - move_all_items(self.list_ignore, self.list_include) - self.fix_buttons() - - def remove_include_all(self): - move_all_items(self.list_include, self.list_ignore) - self.fix_buttons() - - def add_exclude(self): - move_selected_items(self.list_ignore, self.list_exclude) - self.fix_buttons() - - def remove_exclude(self): - move_selected_items(self.list_exclude, self.list_ignore) - self.fix_buttons() - - def add_exclude_all(self): - move_all_items(self.list_ignore, self.list_exclude) - self.fix_buttons() - - def remove_exclude_all(self): - move_all_items(self.list_exclude, self.list_ignore) - self.fix_buttons() - - def include_all(self): - move_all_items(self.list_ignore, self.list_include) - move_all_items(self.list_exclude, self.list_include) - self.fix_buttons() - - def exclude_all(self): - move_all_items(self.list_ignore, self.list_exclude) - move_all_items(self.list_include, self.list_exclude) - self.fix_buttons() - - def clear_all(self): - move_all_items(self.list_include, self.list_ignore) - move_all_items(self.list_exclude, self.list_ignore) - self.fix_buttons() - def get_selected_types_include(self): - return [self.image_types_by_display_title[self.list_include.item(index).text()] for index in range(self.list_include.count())] or ['front'] + return [self.list_include.item(index).data(QtCore.Qt.UserRole) for index in range(self.list_include.count())] or ['front'] def get_selected_types_exclude(self): - return [self.image_types_by_display_title[self.list_exclude.item(index).text()] for index in range(self.list_exclude.count())] or ['none'] + return [self.list_exclude.item(index).data(QtCore.Qt.UserRole) for index in range(self.list_exclude.count())] or ['none'] - def focus_set_include(self): - clear_listbox_focus(self.list_exclude) - clear_listbox_focus(self.list_ignore) - self.fix_buttons() - - def focus_set_exclude(self): - clear_listbox_focus(self.list_include) - clear_listbox_focus(self.list_ignore) - self.fix_buttons() - - def focus_set_ignore(self): - clear_listbox_focus(self.list_include) - clear_listbox_focus(self.list_exclude) - self.fix_buttons() - - def focus_clear_all(self): - clear_listbox_focus(self.list_include) - clear_listbox_focus(self.list_exclude) - clear_listbox_focus(self.list_ignore) - self.fix_buttons() + def clear_focus(self, lists): + for temp_list in lists: + temp_list.clearSelection() + self.set_buttons_enabled_state() def reset_to_defaults(self): self.fill_lists(_CAA_IMAGE_TYPE_DEFAULT_INCLUDE, _CAA_IMAGE_TYPE_DEFAULT_EXCLUDE) - self.fix_buttons() + self.set_buttons_enabled_state() - def fix_buttons(self): + def set_buttons_enabled_state(self): has_items_include = self.list_include.count() has_items_exclude = self.list_exclude.count() has_items_ignore = self.list_ignore.count() - has_selected_include = True if self.list_include.selectedItems() else False - has_selected_exclude = True if self.list_exclude.selectedItems() else False - has_selected_ignore = True if self.list_ignore.selectedItems() else False + has_selected_include = bool(self.list_include.selectedItems()) + has_selected_exclude = bool(self.list_exclude.selectedItems()) + has_selected_ignore = bool(self.list_ignore.selectedItems()) # "Include" list buttons - buttons = self.arrows_include.findChildren(QtWidgets.QPushButton) - buttons[0].setEnabled(has_items_ignore and has_selected_ignore) # '<' - buttons[1].setEnabled(has_items_ignore) # '<<' - buttons[2].setEnabled(has_items_include and has_selected_include) # '>' - buttons[3].setEnabled(has_items_include) # '>>' + self.arrows_include.button_add.setEnabled(has_items_ignore and has_selected_ignore) + self.arrows_include.button_add_all.setEnabled(has_items_ignore) + self.arrows_include.button_remove.setEnabled(has_items_include and has_selected_include) + self.arrows_include.button_remove_all.setEnabled(has_items_include) # "Exclude" list buttons - buttons = self.arrows_exclude.findChildren(QtWidgets.QPushButton) - buttons[0].setEnabled(has_items_ignore and has_selected_ignore) # '>' - buttons[1].setEnabled(has_items_ignore) # '>>' - buttons[2].setEnabled(has_items_exclude and has_selected_exclude) # '<' - buttons[3].setEnabled(has_items_exclude) # '<<' + self.arrows_exclude.button_add.setEnabled(has_items_ignore and has_selected_ignore) + self.arrows_exclude.button_add_all.setEnabled(has_items_ignore) + self.arrows_exclude.button_remove.setEnabled(has_items_exclude and has_selected_exclude) + self.arrows_exclude.button_remove_all.setEnabled(has_items_exclude) @staticmethod def run(parent=None, types_include=None, types_exclude=None): @@ -420,8 +426,7 @@ class ProviderOptionsCaa(ProviderOptions): config.BoolOption("setting", "caa_save_single_front_image", False), config.BoolOption("setting", "caa_approved_only", False), config.BoolOption("setting", "caa_image_type_as_filename", False), - config.IntOption("setting", "caa_image_size", - _CAA_IMAGE_SIZE_DEFAULT), + config.IntOption("setting", "caa_image_size", _CAA_IMAGE_SIZE_DEFAULT), config.ListOption("setting", "caa_image_types", _CAA_IMAGE_TYPE_DEFAULT_INCLUDE), config.BoolOption("setting", "caa_restrict_image_types", True), config.ListOption("setting", "caa_image_types_to_omit", _CAA_IMAGE_TYPE_DEFAULT_EXCLUDE), @@ -476,7 +481,6 @@ class ProviderOptionsCaa(ProviderOptions): config.setting["caa_image_types_to_omit"] = types_to_omit - class CoverArtProviderCaa(CoverArtProvider): """Get cover art from Cover Art Archive using release mbid""" @@ -501,16 +505,14 @@ class CoverArtProviderCaa(CoverArtProvider): # MB web service indicates if CAA has artwork # https://tickets.metabrainz.org/browse/MBS-4536 if 'cover-art-archive' not in self.release: - log.debug("No Cover Art Archive information for %s" - % self.release['id']) + log.debug('No Cover Art Archive information for {release_id}'.format(release_id=self.release['id'])) return False caa_node = self.release['cover-art-archive'] caa_has_suitable_artwork = caa_node['artwork'] if not caa_has_suitable_artwork: - log.debug("There are no images in the Cover Art Archive for %s" - % self.release['id']) + log.debug('There are no images in the Cover Art Archive for {release_id}'.format(release_id=self.release['id'])) return False if self.restrict_types: @@ -539,11 +541,9 @@ class CoverArtProviderCaa(CoverArtProvider): caa_has_suitable_artwork = front_in_caa or back_in_caa if not caa_has_suitable_artwork: - log.debug("There are no suitable images in the Cover Art Archive for %s" - % self.release['id']) + log.debug('There are no suitable images in the Cover Art Archive for {release_id}'.format(release_id=self.release['id'])) else: - log.debug("There are suitable images in the Cover Art Archive for %s" - % self.release['id']) + log.debug('There are suitable images in the Cover Art Archive for {release_id}'.format(release_id=self.release['id'])) return caa_has_suitable_artwork @@ -553,7 +553,7 @@ class CoverArtProviderCaa(CoverArtProvider): self.coverart.front_image_found: return False if self.restrict_types and not self.len_caa_types: - log.debug("User disabled all Cover Art Archive types") + log.debug('User disabled all Cover Art Archive types') return False return self._has_suitable_artwork @@ -609,12 +609,15 @@ class CoverArtProviderCaa(CoverArtProvider): if types and self.caa_types_to_omit: types = not set(image["types"]).intersection( set(self.caa_types_to_omit)) - log.debug('CAA image %s: %s %s' % ('accepted' if types else 'rejected', image['image'], image['types'],)) + log.debug('CAA image {status}: {image_name} {image_types}'.format( + status=('accepted' if types else 'rejected'), + image_name=image['image'], + image_types=image['types'],) + ) else: types = True if types: - urls = caa_url_fallback_list(config.setting["caa_image_size"], - image["thumbnails"]) + urls = caa_url_fallback_list(config.setting["caa_image_size"], image["thumbnails"]) if not urls or is_pdf: url = image["image"] else: From 32f6b71546f55f806028a0fda84a1c3cfd5fc23a Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Sun, 26 Aug 2018 13:05:00 -0600 Subject: [PATCH 4/5] Replace Qt.QListWidgetItem with QtWidgets.QListWidgetItem - Move selected items list generator to ListBox class --- picard/coverart/providers/caa.py | 47 +++++++++++++------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/picard/coverart/providers/caa.py b/picard/coverart/providers/caa.py index a7fbc57f5..015b23553 100644 --- a/picard/coverart/providers/caa.py +++ b/picard/coverart/providers/caa.py @@ -29,7 +29,6 @@ from collections import ( from functools import partial from PyQt5 import ( - Qt, QtCore, QtWidgets, ) @@ -199,6 +198,10 @@ class ListBox(QtWidgets.QListWidget): if callback: callback() + def all_items_data(self, role=QtCore.Qt.UserRole): + for index in range(self.count()): + yield self.item(index).data(role) + class CAATypesSelectorDialog(QtWidgets.QDialog): """Display dialog box to select the CAA image types to include and exclude from download and use. @@ -243,43 +246,31 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): gridlayout = QtWidgets.QGridLayout() grid.setLayout(gridlayout) - row = 0 - column = 0 - item = QtWidgets.QLabel() - item.setText(_("Include types list")) - gridlayout.addWidget(item, row, column) - - column = 4 - item = QtWidgets.QLabel() - item.setText(_("Exclude types list")) - gridlayout.addWidget(item, row, column) - - row = 1 - column = 0 - gridlayout.addWidget(self.list_include, row, column) - - column = 1 self.arrows_include = ArrowsColumn( self.list_include, self.list_ignore, callback=self.set_buttons_enabled_state, ) - gridlayout.addWidget(self.arrows_include, row, column) - column = 2 - gridlayout.addWidget(self.list_ignore, row, column) - - column = 3 self.arrows_exclude = ArrowsColumn( self.list_exclude, self.list_ignore, callback=self.set_buttons_enabled_state, reverse=True ) - gridlayout.addWidget(self.arrows_exclude, row, column) - column = 4 - gridlayout.addWidget(self.list_exclude, row, column) + def add_widget(row=0, column=0, widget=None): + gridlayout.addWidget(widget, row, column) + + add_widget(row=0, column=0, widget=QtWidgets.QLabel(_("Include types list"))) + add_widget(row=1, column=0, widget=self.list_include) + + add_widget(row=1, column=1, widget=self.arrows_include) + add_widget(row=1, column=2, widget=self.list_ignore) + add_widget(row=1, column=3, widget=self.arrows_exclude) + + add_widget(row=0, column=4, widget=QtWidgets.QLabel(_("Exclude types list"))) + add_widget(row=1, column=4, widget=self.list_exclude) self.layout.addWidget(grid) @@ -358,7 +349,7 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): for caa_type in CAA_TYPES: name = caa_type['name'] title = translate_caa_type(caa_type['title']) - item = Qt.QListWidgetItem(title) + item = QtWidgets.QListWidgetItem(title) item.setData(QtCore.Qt.UserRole, name) if name in includes: self.list_include.addItem(item) @@ -371,10 +362,10 @@ class CAATypesSelectorDialog(QtWidgets.QDialog): webbrowser2.goto('doc_cover_art_types') def get_selected_types_include(self): - return [self.list_include.item(index).data(QtCore.Qt.UserRole) for index in range(self.list_include.count())] or ['front'] + return list(self.list_include.all_items_data()) or ['front'] def get_selected_types_exclude(self): - return [self.list_exclude.item(index).data(QtCore.Qt.UserRole) for index in range(self.list_exclude.count())] or ['none'] + return list(self.list_exclude.all_items_data()) or ['none'] def clear_focus(self, lists): for temp_list in lists: From de319e73b77a137d51ae0c715890af59a0bad55c Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Mon, 27 Aug 2018 09:48:11 -0600 Subject: [PATCH 5/5] Remove label test lines --- picard/coverart/providers/caa.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/picard/coverart/providers/caa.py b/picard/coverart/providers/caa.py index 015b23553..2fed071d8 100644 --- a/picard/coverart/providers/caa.py +++ b/picard/coverart/providers/caa.py @@ -111,8 +111,6 @@ class ArrowButton(QtWidgets.QPushButton): ARROW_BUTTON_HEIGHT = 20 def __init__(self, label, command=None, parent=None): - if label is None: - label = '.' super().__init__(label, parent=parent) if command is not None: self.clicked.connect(command)