From 9359cd877dda3ce794440a03b00c0194adecaa9f Mon Sep 17 00:00:00 2001 From: Mizaki Date: Sat, 27 Apr 2024 00:50:12 +0100 Subject: [PATCH] Switch to using list for storing read styles --- comictaggerlib/ctsettings/file.py | 11 +- .../ctsettings/settngs_namespace.py | 4 +- comictaggerlib/taggerwindow.py | 19 ++- comictaggerlib/ui/customwidgets.py | 153 +++++++++--------- 4 files changed, 100 insertions(+), 87 deletions(-) diff --git a/comictaggerlib/ctsettings/file.py b/comictaggerlib/ctsettings/file.py index b671001..a6066e6 100644 --- a/comictaggerlib/ctsettings/file.py +++ b/comictaggerlib/ctsettings/file.py @@ -32,7 +32,7 @@ def internal(parser: settngs.Manager) -> None: # automatic settings parser.add_setting("install_id", default=uuid.uuid4().hex, cmdline=False) parser.add_setting("save_data_style", default=["cbi"], cmdline=False) - parser.add_setting("load_data_style", default=[{"cbi": 0}], cmdline=False) + parser.add_setting("load_data_style", default=["cbi"], cmdline=False) parser.add_setting("last_opened_folder", default="", cmdline=False) parser.add_setting("window_width", default=0, cmdline=False) parser.add_setting("window_height", default=0, cmdline=False) @@ -279,6 +279,15 @@ def migrate_settings(config: settngs.Config[ct_ns]) -> settngs.Config[ct_ns]: else: config[0].internal__save_data_style = ["cbi"] + load_style = config[0].internal__load_data_style + if not isinstance(load_style, list): + if isinstance(load_style, int) and load_style in (0, 1, 2): + config[0].internal__load_data_style = [original_types[load_style]] + elif isinstance(load_style, str): + config[0].internal__load_data_style = [load_style] + else: + config[0].internal__load_data_style = ["cbi"] + return config diff --git a/comictaggerlib/ctsettings/settngs_namespace.py b/comictaggerlib/ctsettings/settngs_namespace.py index b5022e0..151d2b2 100644 --- a/comictaggerlib/ctsettings/settngs_namespace.py +++ b/comictaggerlib/ctsettings/settngs_namespace.py @@ -41,7 +41,7 @@ class SettngsNS(settngs.TypedNS): internal__install_id: str internal__save_data_style: list[str] - internal__load_data_style: dict[str, int] + internal__load_data_style: list[str] internal__last_opened_folder: str internal__window_width: int internal__window_height: int @@ -149,7 +149,7 @@ class Runtime_Options(typing.TypedDict): class internal(typing.TypedDict): install_id: str save_data_style: list[str] - load_data_style: str + load_data_style: list[str] last_opened_folder: str window_width: int window_height: int diff --git a/comictaggerlib/taggerwindow.py b/comictaggerlib/taggerwindow.py index 5ef6cf8..df4f70a 100644 --- a/comictaggerlib/taggerwindow.py +++ b/comictaggerlib/taggerwindow.py @@ -223,11 +223,11 @@ class TaggerWindow(QtWidgets.QMainWindow): for style in config[0].internal__save_data_style: if style not in metadata_styles: config[0].internal__save_data_style.remove(style) - for style in config[0].internal__load_data_style.keys(): + for style in config[0].internal__load_data_style: if style not in metadata_styles: - del config[0].internal__load_data_style[style] + config[0].internal__load_data_style.remove(style) self.save_data_styles: list[str] = config[0].internal__save_data_style - self.load_data_styles: dict[str, int] = config[0].internal__load_data_style + self.load_data_styles: list[str] = config[0].internal__load_data_style self.setAcceptDrops(True) self.view_tag_actions, self.remove_tag_actions = self.tag_actions() @@ -1399,9 +1399,12 @@ class TaggerWindow(QtWidgets.QMainWindow): def adjust_load_style_combo(self) -> None: # select the enabled styles - unchecked = set(metadata_styles.keys()) - set(self.load_data_styles.keys()) - for style, order in self.load_data_styles.items(): - self.cbLoadDataStyle.setItemChecked(self.cbLoadDataStyle.findData(style), True, order) + unchecked = set(metadata_styles.keys()) - set(self.load_data_styles) + for i, style in enumerate(self.load_data_styles): + item_idx = self.cbLoadDataStyle.findData(style) + self.cbLoadDataStyle.setItemChecked(item_idx, True) + # Order matters so move it + self.cbLoadDataStyle.moveItem(item_idx, row=i) for style in unchecked: self.cbLoadDataStyle.setItemChecked(self.cbLoadDataStyle.findData(style), False) @@ -1424,10 +1427,10 @@ class TaggerWindow(QtWidgets.QMainWindow): for style in metadata_styles.values(): if self.config[0].General__use_short_metadata_names: self.cbSaveDataStyle.addItem(style.short_name.upper(), style.short_name) - self.cbLoadDataStyle.addItem(style.short_name.upper(), {style.short_name: -1}) + self.cbLoadDataStyle.addItem(style.short_name.upper(), style.short_name) else: self.cbSaveDataStyle.addItem(style.name(), style.short_name) - self.cbLoadDataStyle.addItem(style.name(), {style.short_name: -1}) + self.cbLoadDataStyle.addItem(style.name(), style.short_name) def populate_combo_boxes(self) -> None: self.populate_style_names() diff --git a/comictaggerlib/ui/customwidgets.py b/comictaggerlib/ui/customwidgets.py index 0ad99c1..063d63f 100644 --- a/comictaggerlib/ui/customwidgets.py +++ b/comictaggerlib/ui/customwidgets.py @@ -160,7 +160,11 @@ class HoverQLabel(QtWidgets.QLabel): # Place 'up' button on right side self.button_up.resize(self.button_up.sizeHint()) - def _showHideButtons(self, index: QModelIndex) -> None: + def hideButtons(self) -> None: + self.button_up.hide() + self.button_down.hide() + + def showHideButtons(self, index: QModelIndex) -> None: # TODO Better to iterate over all? Send in check state too? item = self.combobox.tableWidget.item(index.row(), 1) item_checked = item.checkState() @@ -198,11 +202,11 @@ class HoverQLabel(QtWidgets.QLabel): def button_up_clicked(self) -> None: index: QModelIndex = self.combobox.tableWidget.indexAt(self.pos()) - self.combobox._move_item(index, True) + self.combobox.moveItem(index, True) def button_down_clicked(self) -> None: index: QModelIndex = self.combobox.tableWidget.indexAt(self.pos()) - self.combobox._move_item(index, False) + self.combobox.moveItem(index, False) class TableComboBox(QtWidgets.QComboBox): @@ -251,14 +255,14 @@ class TableComboBox(QtWidgets.QComboBox): if prev_row == -1: # First time open cur_index = self.tableWidget.indexFromItem(self.tableWidget.item(cur_row, 0)) - self.tableWidget.cellWidget(cur_row, 2)._showHideButtons(cur_index) + self.tableWidget.cellWidget(cur_row, 2).showHideButtons(cur_index) elif cur_row != prev_row: # Hide previous prev_index = self.tableWidget.indexFromItem(self.tableWidget.item(prev_row, 0)) - self.tableWidget.cellWidget(prev_row, 2)._showHideButtons(prev_index) + self.tableWidget.cellWidget(prev_row, 2).showHideButtons(prev_index) # Show current cur_index = self.tableWidget.indexFromItem(self.tableWidget.item(cur_row, 0)) - self.tableWidget.cellWidget(cur_row, 2)._showHideButtons(cur_index) + self.tableWidget.cellWidget(cur_row, 2).showHideButtons(cur_index) def _longest_label(self) -> None: # Depending on "short" names for metadata, "Read Style" header or metadata name may be longer @@ -327,29 +331,35 @@ class TableComboBox(QtWidgets.QComboBox): self.tableWidget.setRowCount(0) self.longest = 0 - def _move_item(self, index: QModelIndex, up: bool) -> None: - """Move an item up or down in order""" - adjust = -1 if up else 1 - cur_item = self.tableWidget.item(index.row(), 0) - cur_item_data = cur_item.data(Qt.UserRole) - cur_key, cur_value = next(iter(cur_item_data.items())) + def moveItem(self, index: QModelIndex, up: bool = False, row: int | None = None) -> None: + """'Move' an item. Really swap the data and titles around on the two rows""" + if row is None: + adjust = -1 if up else 1 + row = index.row() + adjust - swap_item = self.tableWidget.item(index.row() + adjust, 0) - swap_item_data = swap_item.data(Qt.UserRole) - swap_key, swap_value = next(iter(swap_item_data.items())) + # Grab values for the rows to swap + cur_data = self.tableWidget.item(index.row(), 0).data(Qt.UserRole) + cur_title = self.tableWidget.cellWidget(index.row(), 2).text() + swap_data = self.tableWidget.item(row, 0).data(Qt.UserRole) + swap_title = self.tableWidget.cellWidget(row, 2).text() - # While the buttons should not be enabled, check for valid numbers to swap anyway - if cur_value != -1 and swap_value != -1: - cur_item.setData(Qt.UserRole, {cur_key: swap_value}) - swap_item.setData(Qt.UserRole, {swap_key: cur_value}) + self.tableWidget.item(row, 0).setData(Qt.UserRole, cur_data) + self.tableWidget.cellWidget(row, 2).setText(cur_title) + self.tableWidget.item(index.row(), 0).setData(Qt.UserRole, swap_data) + self.tableWidget.cellWidget(index.row(), 2).setText(swap_title) - self._updateLabels() - self.itemChanged.emit() - # Selected (highlighted) row moves so is no longer under the mouse - self.tableWidget.selectRow(index.row()) + # Hide buttons and clear selection to indicate to user an action has taken place + self.tableWidget.cellWidget(index.row(), 2).hideButtons() + self.tableWidget.clearSelection() - def addItem(self, text: str = "", data: Any | None = None) -> None: - rowPosition = self.tableWidget.rowCount() + self.itemChanged.emit() + + def addItem(self, text: str = "", data: Any | None = None, rowPosition: int | None = None) -> None: + rowPosition = ( + self.tableWidget.rowCount() + if rowPosition is None or rowPosition > self.tableWidget.rowCount() + else rowPosition + ) self.tableWidget.insertRow(rowPosition) sortTblItem = SortLabelTableWidgetItem() @@ -372,57 +382,62 @@ class TableComboBox(QtWidgets.QComboBox): def findData(self, data: str, role: int = Qt.UserRole) -> QModelIndex | None: for i in range(self.count()): item = self.itemData(i) - k = list(item.keys())[0] - if k == data: + if item == data: return self.tableWidget.indexFromItem(self.tableWidget.item(i, 0)) return None - def currentData(self) -> dict[str, int]: - res = {} + def currentData(self) -> list[str]: + res = [] for i in range(self.count()): item = self.tableWidget.item(i, 1) if item.checkState() == Qt.Checked: - res.update(self.itemData(i)) + res.append(self.itemData(i)) return res def _setOrderNumbers(self) -> None: - """Recalculate the order numbers; 0,2 -> 0,1""" + """Recalculate the order numbers""" current_data = self.currentData() - # Convert dict to list of tuples - data = list(current_data.items()) - # Sort the list by value (second element in the tuple) - sorted_data = sorted(data, key=lambda x: x[1]) - for i, value in enumerate(sorted_data): - for j in range(self.count()): - item = self.itemData(j) - if list(item.keys())[0] == value[0]: - self.tableWidget.item(j, 0).setData(Qt.UserRole, {value[0]: i}) + text = "-" + + for j in range(self.count()): + item = self.itemData(j) + for i, cur in enumerate(current_data): + if item == cur: + text = str(i + 1) + + self.tableWidget.item(j, 0).setText(text) def _updateLabels(self) -> None: """Update order label text and set button enablement""" cur_data_len = len(self.currentData()) for i in range(self.count()): label = self.tableWidget.item(i, 0) + checked = self.tableWidget.item(i, 1).checkState() data = self.itemData(i) - k, val = next(iter(data.items())) - val += 1 - text = "-" if val == 0 else str(val) - label.setText(text) + label_num = "-" + enable_up = True + enable_down = True - # Enable all buttons - self.tableWidget.cellWidget(i, 2).button_up.setEnabled(True) - self.tableWidget.cellWidget(i, 2).button_down.setEnabled(True) + # Go through currentData + for j, cur_data in enumerate(self.currentData()): + if cur_data == data: + label_num = str(j + 1) + if cur_data_len == 1: + enable_up = False + enable_down = False + elif j == 0: + enable_up = False + elif j + 1 == cur_data_len: + enable_down = False - # Disable top up button and bottom down button - if val == 1: - self.tableWidget.cellWidget(i, 2).button_up.setEnabled(False) - # Disable the down button if single item. Show buttons even if disabled to indicate checked - if val == cur_data_len: - self.tableWidget.cellWidget(i, 2).button_down.setEnabled(False) - elif val == cur_data_len: - self.tableWidget.cellWidget(i, 2).button_down.setEnabled(False) + label.setText(label_num) + + # Enable/disable hover buttons + self.tableWidget.cellWidget(i, 2).button_up.setEnabled(enable_up) + self.tableWidget.cellWidget(i, 2).button_down.setEnabled(enable_down) self.tableWidget.sortItems(0) + self.tableWidget.clearSelection() def _nextOrderNumber(self) -> int: return len(self.currentData()) - 1 @@ -453,7 +468,7 @@ class TableComboBox(QtWidgets.QComboBox): self.setCurrentIndex(-1) self.setPlaceholderText(elidedText) - def setItemChecked(self, index: QModelIndex, state: bool, order: int = -1) -> None: + def setItemChecked(self, index: QModelIndex, state: bool) -> None: if index is None: return qt_state = Qt.Checked if state else Qt.Unchecked @@ -467,27 +482,13 @@ class TableComboBox(QtWidgets.QComboBox): if current_len > 0: item.setCheckState(qt_state) - item_data: dict[str, int] = self.itemData(index.row()) - key_name = list(item_data.keys())[0] - if state: - order_num = order if order != -1 else self._nextOrderNumber() - data = {key_name: order_num} - self.tableWidget.item(index.row(), 0).setText(str(order_num + 1)) - self.tableWidget.item(index.row(), 0).setData(Qt.UserRole, data) - else: - data = {key_name: -1} - self.tableWidget.item(index.row(), 0).setText("-") - self.tableWidget.item(index.row(), 0).setData(Qt.UserRole, data) - # Any number may have been removed so reevaluate all - self._setOrderNumbers() - - self.itemChanged.emit() - self._updateText() + if not state: + # Hide hover buttons of shown row (before it changes row) + self.tableWidget.cellWidget(index.row(), 2).showHideButtons(index) + self._setOrderNumbers() self._updateLabels() - # Check if buttons need to be shown or hidden - self.tableWidget.cellWidget(index.row(), 2)._showHideButtons(index) - # As the sort may have moved the highlighted row, select what's under the mouse - self.tableWidget.selectRow(index.row()) + self._updateText() + self.itemChanged.emit() def toggleItem(self, index: QModelIndex) -> None: cxb_index = self.model().index(index.row(), 1)