Skip to content

Commit

Permalink
Merge branch 'master' into issue_2794
Browse files Browse the repository at this point in the history
  • Loading branch information
ptsavol committed Sep 11, 2024
2 parents db8a7b0 + 6cdd3a3 commit 95fd6e7
Show file tree
Hide file tree
Showing 12 changed files with 658 additions and 50 deletions.
18 changes: 12 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)

### Added

### Changed

### Deprecated

### Removed

### Fixed

## [0.8.3]

### Added

- Entity group column in *Add entities* dialog. If filled, the created entity will be added to the specified group.
If the group doesn't yet exist, it will be created.
- Native kernel (i.e. python3 for Python) can now be used in the Detached Console or in Tool execution.
Expand All @@ -24,19 +36,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
- One dimensional entities can now also be added through *Parameter value* and *Entity alternative* tables.
- Special data types like dates, times and booleans are now properly pasted from Excel.

### Deprecated

### Removed

### Fixed
- [Bundled App] Fixed execution in Jupyter Console and opening Detached Consoles by adding jupyter-client and
qtconsole packages to the bundle.
- [Bundled App] Fixed creating new kernel specs in Settings->Tools by adding ipykernel package to the
**embedded Python**.
- [Bundled App] Fixed 'Install Julia' button in Settings->Tools by adding the jill package to the **embedded Python**.

### Security

## [0.8.2]

### Added
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ dependencies = [
"PySide6 >= 6.5.0, != 6.5.3, != 6.6.3, != 6.7.0",
"jupyter_client >=6.0",
"qtconsole >=5.1",
"spinedb_api>=0.31.2",
"spine_engine>=0.24.1",
"spinedb_api>=0.31.3",
"spine_engine>=0.24.2",
"numpy >=1.20.2",
"matplotlib >= 3.5",
"scipy >=1.7.1",
Expand All @@ -26,7 +26,7 @@ dependencies = [
"Pygments >=2.8",
"jill >=0.9.2",
"pyzmq >=21.0",
"spine_items>=0.22.2",
"spine_items>=0.22.3",
]

[project.urls]
Expand Down
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
4 changes: 2 additions & 2 deletions spinetoolbox/project_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,8 @@ def __init__(self, project, jump, jump_properties, condition):
self._jump_properties = jump_properties
self._jump_source = jump.source
self._jump_destination = jump.destination
self._condition = condition
self._previous_condition = jump.condition
self._condition = dict(condition)
self._previous_condition = dict(jump.condition)
self.setText(f"change loop condition for jump {jump.name}")

def redo(self):
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
5 changes: 4 additions & 1 deletion spinetoolbox/spine_engine_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,10 @@ class RemoteSpineEngineManager(SpineEngineManagerBase):
"""Responsible for remote project execution."""

def __init__(self, job_id=""):
"""Initializer."""
"""
Args:
job_id (str): Job id of ProjectExtractionService for finding the extracted project on server
"""
super().__init__()
self._runner = threading.Thread(name="RemoteSpineEngineManagerRunnerThread", target=self._run)
self._engine_data = None
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 95fd6e7

Please sign in to comment.