Skip to content

Commit

Permalink
Fetch parameter values in entity graph (to get fixed positions)
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelma committed Sep 1, 2023
1 parent 5687dcf commit 7145c94
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 36 deletions.
22 changes: 5 additions & 17 deletions spinetoolbox/spine_db_editor/widgets/custom_qwidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,7 @@ class ProgressBarWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAttribute(Qt.WA_DeleteOnClose)
inner_widget = QWidget(self)
layout = QHBoxLayout(self)
layout.addStretch()
layout.addWidget(inner_widget)
layout.addStretch()
self._label = QLabel()
self._label.setStyleSheet("QLabel{color:white; font-weight: bold; font-size:18px;}")
self._label.setAlignment(Qt.AlignHCenter)
self._progress_bar = QProgressBar()
button_box = QDialogButtonBox()
button_box.setCenterButtons(True)
Expand All @@ -147,30 +140,25 @@ def __init__(self, parent=None):
lambda checked: self._previews_button.setText(f"{'Hide' if checked else 'Show'} previews")
)
self.stop_button = button_box.addButton("Stop", QDialogButtonBox.ButtonRole.NoRole)
inner_layout = QVBoxLayout(inner_widget)
inner_layout.addStretch()
inner_layout.addWidget(self._label)
inner_layout.addWidget(self._progress_bar)
inner_layout.addWidget(button_box)
inner_layout.addStretch()
layout.addWidget(self._progress_bar)
layout.addWidget(button_box)
self._layout_gen = None

def set_layout_generator(self, layout_generator):
if self._layout_gen is not None:
self._layout_gen.finished.disconnect(self.hide)
self._layout_gen.progressed.disconnect(self._progress_bar.setValue)
self._layout_gen.msg.disconnect(self._progress_bar.setFormat)
self._previews_button.toggled.disconnect(self._layout_gen.set_show_previews)
self.stop_button.clicked.disconnect(self._layout_gen.stop)
self._layout_gen = layout_generator
self._label.setText(f"Processing {self._layout_gen.vertex_count} elements")
self._progress_bar.setRange(0, self._layout_gen.max_iters - 1)
self._progress_bar.setFormat(f"Processing {self._layout_gen.vertex_count} elements...")
self._progress_bar.setRange(0, self._layout_gen.max_iters + 2)
self._progress_bar.setValue(0)
self._previews_button.toggled.connect(self._layout_gen.set_show_previews)
self.stop_button.clicked.connect(self._layout_gen.stop)
self._layout_gen.finished.connect(self.hide)
self._layout_gen.progressed.connect(self._progress_bar.setValue)
self._layout_gen.progressed.connect(self.show)
self._layout_gen.msg.connect(self._progress_bar.setFormat)

def paintEvent(self, event):
painter = QPainter(self)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class Signals(QObject):
finished = Signal(object)
layout_available = Signal(object, object, object)
progressed = Signal(int)
msg = Signal(str)

def __init__(
self,
Expand All @@ -74,7 +73,6 @@ def __init__(
preview_available=self._preview_available,
layout_available=self._layout_available,
layout_progressed=self._layout_progressed,
message_available=self._message_available,
)
self.vertex_count = vertex_count
self.max_iters = max_iters
Expand All @@ -85,7 +83,6 @@ def __init__(
self.finished = self._signals.finished
self.layout_available = self._signals.layout_available
self.progressed = self._signals.progressed
self.msg = self._signals.msg

@Slot(bool)
def stop(self, _checked=False):
Expand All @@ -101,9 +98,6 @@ def _is_stopped(self):
def _layout_progressed(self, iteration):
self.progressed.emit(iteration)

def _message_available(self, text):
self.msg.emit(text)

def _layout_available(self, x, y):
self.layout_available.emit(self._id, x, y)

Expand Down
31 changes: 25 additions & 6 deletions spinetoolbox/spine_db_editor/widgets/graph_view_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,23 @@ def __init__(self, *args, **kwargs):
self._extend_graph_timer.setInterval(100)
self._extend_graph_timer.timeout.connect(self.build_graph)
self._extending_graph = False
self._entity_fetch_parent = None

def _renew_fetch_parents(self):
if self._entity_fetch_parent is not None:
self._entity_fetch_parent.set_obsolete(True)
self._entity_fetch_parent = FlexibleFetchParent(
"entity",
handle_items_added=self._graph_handle_entities_added,
handle_items_removed=self._graph_handle_entities_removed,
handle_items_updated=self._graph_handle_entities_updated,
owner=self,
)
self._parameter_value_fetch_parent = FlexibleFetchParent(
"parameter_value", handle_items_added=self._graph_handle_parameter_values_added, owner=self
)

def _graph_fetch_more(self):
for db_map in self.db_maps:
if self.db_mngr.can_fetch_more(db_map, self._entity_fetch_parent):
self.db_mngr.fetch_more(db_map, self._entity_fetch_parent)
if self.db_mngr.can_fetch_more(db_map, self._parameter_value_fetch_parent):
self.db_mngr.fetch_more(db_map, self._parameter_value_fetch_parent)

@Slot(bool)
def _stop_extending_graph(self, _=False):
Expand Down Expand Up @@ -114,6 +116,9 @@ def _graph_handle_entities_added(self, db_map_data):
"""
new_db_map_id_sets = self.add_db_map_ids_to_items(db_map_data)
if not new_db_map_id_sets:
for db_map in self.db_maps:
if self.db_mngr.can_fetch_more(db_map, self._entity_fetch_parent):
self.db_mngr.fetch_more(db_map, self._entity_fetch_parent)
return
if self._pos_for_added_entities is not None:
spread = self.VERTEX_EXTENT * self.ui.graphicsView.zoom_factor
Expand All @@ -133,6 +138,8 @@ def _graph_handle_entities_added(self, db_map_data):
self._end_connect_entities()
elif self._extending_graph:
self._extend_graph_timer.start()
else:
self.rebuild_graph()

def _graph_handle_entities_removed(self, db_map_data):
"""Runs when entities are removed from the db. Rebuilds graph if needed.
Expand Down Expand Up @@ -211,6 +218,18 @@ def hide_removed_entities(self, db_map_data):
item.setVisible(False)
self.scene = scene

def _graph_handle_parameter_values_added(self, db_map_data):
pnames = {x["parameter_definition_name"] for db_map in self.db_maps for x in db_map_data.get(db_map, ())}
if not (pnames & {self.ui.graphicsView.pos_x_parameter, self.ui.graphicsView.pos_y_parameter}):
for db_map in self.db_maps:
if self.db_mngr.can_fetch_more(db_map, self._parameter_value_fetch_parent):
self.db_mngr.fetch_more(db_map, self._parameter_value_fetch_parent)
return
if self._extending_graph:
self._extend_graph_timer.start()
else:
self.rebuild_graph()

@Slot(bool)
def _handle_entity_graph_visibility_changed(self, visible):
if not visible:
Expand All @@ -222,7 +241,6 @@ def _handle_entity_graph_visibility_changed(self, visible):
@Slot(dict)
def _handle_entity_tree_selection_changed_in_graph(self, selected):
"""Stores the given selection of entity tree indexes and builds graph."""
self._renew_fetch_parents()
self.selected_tree_inds = selected
self.added_db_map_entity_ids.clear()
self._extending_graph = True
Expand Down Expand Up @@ -256,6 +274,7 @@ def build_graph(self, persistent=False):
layout_gen.layout_available.connect(self._complete_graph)
layout_gen.finished.connect(lambda id_: self.layout_gens.pop(id_, None)) # Lambda to avoid issues in Python 3.7
self._thread_pool.start(layout_gen)
self._graph_fetch_more()

def _stop_layout_generators(self):
for layout_gen in self.layout_gens.values():
Expand Down
9 changes: 5 additions & 4 deletions spinetoolbox/spine_db_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1232,10 +1232,9 @@ def do_remove_items(self, db_map, item_type, ids):
"""Removes items from database.
Args:
db_map: DatabaseMapping instance
item_type (str): database item type
db_map_ids (dict): mapping DatabaseMapping to removable ids
callback (Callable, optional): function to call after removal is finished
committing_callback (Callable, optional): function to call after removal has been committed
ids (set): ids to remove
"""
try:
worker = self._get_worker(db_map)
Expand All @@ -1248,7 +1247,9 @@ def do_restore_items(self, db_map, item_type, ids):
"""Restores items in database.
Args:
db_map_typed_ids (dict): mapping DiffDatabaseMapping to item type (str) to lists of items to restore
db_map: DatabaseMapping instance
item_type (str): database item type
ids (set): ids to restore
"""
try:
worker = self._get_worker(db_map)
Expand Down
10 changes: 7 additions & 3 deletions spinetoolbox/spine_db_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,20 @@ def fetch_more(self, parent):
return
self._parents_fetching[item_type] = {parent}
callback = lambda future: self._handle_query_advanced(item_type, future.result())
self._executor.submit(self._db_map.advance_cache_query, item_type).add_done_callback(callback)
self._executor.submit(self._busy_advance_cache_query, item_type).add_done_callback(callback)
parent.set_busy(True)

@busy_effect
def _busy_advance_cache_query(self, item_type):
return self._db_map.advance_cache_query(item_type)

def _handle_query_advanced(self, item_type, chunk):
self._populate_commit_cache(item_type, chunk)
self._db_mngr.update_icons(self._db_map, item_type, chunk)
for parent in self._parents_fetching.pop(item_type, ()):
self._update_parent(parent)

def _fetch_complete(self, parent):
def _is_fetch_complete(self, parent):
"""Whether fetch is complete for given parent."""
items = self._db_map.cache.get(parent.fetch_item_type, ())
index = parent.index
Expand All @@ -233,7 +237,7 @@ def _fetch_complete(self, parent):

def _update_parent(self, parent):
"""Check if fetch is complete and react accordingly."""
if self._fetch_complete(parent):
if self._is_fetch_complete(parent):
parent.set_fetched(True)
parent.set_busy(False)
else:
Expand Down

0 comments on commit 7145c94

Please sign in to comment.