Skip to content

Commit

Permalink
Fix some warnings from unit tests (#2929)
Browse files Browse the repository at this point in the history
  • Loading branch information
soininen authored Sep 6, 2024
2 parents 27d5f5d + 5163bde commit 6cdd3a3
Show file tree
Hide file tree
Showing 8 changed files with 637 additions and 38 deletions.
35 changes: 18 additions & 17 deletions spinetoolbox/mvcmodels/compound_table_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
"""Models that vertically concatenate two or more table models."""
import bisect
from PySide6.QtCore import QModelIndex, Qt, QTimer, Slot
from ..helpers import rows_to_row_count_tuples
from ..mvcmodels.minimal_table_model import MinimalTableModel


class CompoundTableModel(MinimalTableModel):
"""A model that concatenates several sub table models vertically."""

def __init__(self, parent=None, header=None):
"""Initializes model.
"""
Args:
parent (QObject, optional): the parent object
header (list of str, optional): header labels
Expand Down Expand Up @@ -125,7 +125,7 @@ def _append_row_map(self, row_map):
row_map (list): tuples (model, row number)
"""
for model_row_tup in row_map:
self._inv_row_map[model_row_tup] = self.rowCount()
self._inv_row_map[model_row_tup] = len(self._row_map)
self._row_map.append(model_row_tup)

def _row_map_iterator_for_model(self, model):
Expand Down Expand Up @@ -331,20 +331,21 @@ def _handle_single_model_about_to_be_reset(self, model):
row_map = self._row_map_for_model(model)
if not row_map:
return
try:
first = self._inv_row_map[row_map[0]]
except KeyError:
# Sometimes the submodel may get reset before it has been added to the inverted row map.
# In this case there are no rows to remove, so we can bail out here.
return
last = first + len(row_map) - 1
tail_row_map = self._row_map[last + 1 :]
self.beginRemoveRows(QModelIndex(), first, last)
for key in self._row_map[first:]:
del self._inv_row_map[key]
self._row_map[first:] = []
self._append_row_map(tail_row_map)
self.endRemoveRows()
removed_rows = []
for mapped_row in row_map:
try:
removed_rows.append(self._inv_row_map[mapped_row])
except KeyError:
pass
for first, count in sorted(rows_to_row_count_tuples(removed_rows), reverse=True):
last = first + count - 1
tail_row_map = self._row_map[last + 1 :]
self.beginRemoveRows(QModelIndex(), first, last)
for key in self._row_map[first:]:
del self._inv_row_map[key]
del self._row_map[first:]
self._append_row_map(tail_row_map)
self.endRemoveRows()

def _handle_single_model_reset(self, model):
"""Runs when given model is reset."""
Expand Down
73 changes: 63 additions & 10 deletions spinetoolbox/spine_db_editor/mvcmodels/compound_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def _auto_filter_accepts_model(self, model):
for db_map, entity_class_id in values:
if model.db_map == db_map and (entity_class_id is None or model.entity_class_id == entity_class_id):
break
else: # nobreak
else:
return False
return True

Expand Down Expand Up @@ -391,7 +391,6 @@ def handle_items_removed(self, db_map_data):
Args:
db_map_data (dict): list of removed dict-items keyed by DatabaseMapping
"""
self.layoutAboutToBeChanged.emit()
for db_map, items in db_map_data.items():
if db_map not in self.db_maps:
continue
Expand All @@ -403,23 +402,77 @@ def handle_items_removed(self, db_map_data):
removed_ids = {x["id"] for x in items_per_class.get(model.entity_class_id, {})}
if not removed_ids:
continue
removed_rows = []
removed_invisible_rows = set()
removed_visible_rows = []
for row in range(model.rowCount()):
id_ = model._main_data[row]
if id_ in removed_ids:
removed_rows.append(row)
removed_ids.remove(id_)
if not removed_ids:
break
for row, count in sorted(rows_to_row_count_tuples(removed_rows), reverse=True):
del model._main_data[row : row + count]
if (model, row) in self._inv_row_map:
removed_visible_rows.append(row)
else:
removed_invisible_rows.add(row)
removed_compound_rows = [self._inv_row_map[(model, row)] for row in removed_visible_rows]
if removed_invisible_rows:
new_kept_rows = self._delete_rows_from_single_model(model, removed_invisible_rows)
self._update_single_model_rows_in_row_map(model, new_kept_rows)
for first_compound_row, count in sorted(rows_to_row_count_tuples(removed_compound_rows), reverse=True):
self.beginRemoveRows(QModelIndex(), first_compound_row, first_compound_row + count - 1)
removed_model_rows = {
self._row_map[r][1] for r in range(first_compound_row, first_compound_row + count)
}
new_kept_rows = self._delete_rows_from_single_model(model, removed_model_rows)
for row in removed_model_rows:
del self._inv_row_map[(model, row)]
self._update_single_model_rows_in_row_map(model, new_kept_rows)
del self._row_map[first_compound_row : first_compound_row + count]
for row, mapped_row in enumerate(self._row_map[first_compound_row:]):
self._inv_row_map[mapped_row] = row + first_compound_row
self.endRemoveRows()
if model.rowCount() == 0:
emptied_single_model_indexes.append(model_index)
for model_index in reversed(emptied_single_model_indexes):
model = self.sub_models.pop(model_index)
model.deleteLater()
self._do_refresh()
self.layoutChanged.emit()

def _delete_rows_from_single_model(self, model, rows_to_remove):
"""Removes rows from given single model and computes a map from original rows to retained rows.
Args:
model (SingleModelBase): single model to delete data from
rows_to_remove (set of int): row index that should be removed
Returns:
dict: mapping from original row index to post-removal row index
"""
new_kept_rows = {}
sorted_deleted_rows = []
for row in range(model.rowCount()):
if row in rows_to_remove:
sorted_deleted_rows.append(row)
else:
new_kept_rows[row] = row - len(sorted_deleted_rows)
for row in reversed(sorted_deleted_rows):
del model._main_data[row]
return new_kept_rows

def _update_single_model_rows_in_row_map(self, model, new_rows):
"""Rewrites single model rows in row map.
Args:
model (SingleModelBase): single model whose rows to update
new_rows (dict): mapping from old row index to updated index
"""
new_inv_row_map = {}
for row, new_row in new_rows.items():
try:
compound_row = self._inv_row_map.pop((model, row))
except KeyError:
continue
self._row_map[compound_row] = (model, new_row)
new_inv_row_map[(model, new_row)] = compound_row
for mapped_row, compound_row in new_inv_row_map.items():
self._inv_row_map[mapped_row] = compound_row

def db_item(self, index):
sub_index = self.map_to_sub(index)
Expand Down
2 changes: 1 addition & 1 deletion spinetoolbox/spine_db_editor/widgets/custom_menus.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def __init__(self, parent):
"Clear",
self.clear_recents,
enabled=self.has_recents(),
icon=QIcon(":icons/trash-alt.svg"),
icon=QIcon(":icons/menu_icons/trash-alt.svg"),
)

def has_recents(self):
Expand Down
2 changes: 1 addition & 1 deletion spinetoolbox/widgets/custom_menus.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def __init__(self, parent):
"Clear",
lambda checked=False: self.call_clear_recents(checked),
enabled=self.has_recents(),
icon=QIcon(":icons/trash-alt.svg"),
icon=QIcon(":icons/menu_icons/trash-alt.svg"),
)

def has_recents(self):
Expand Down
Loading

0 comments on commit 6cdd3a3

Please sign in to comment.