Skip to content

Commit

Permalink
Fix opening infinite db editor tabs from same db (#2486)
Browse files Browse the repository at this point in the history
  • Loading branch information
PiispaH authored Jan 15, 2024
1 parent a2cd888 commit 67d9b49
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 13 deletions.
25 changes: 21 additions & 4 deletions spinetoolbox/spine_db_editor/widgets/multi_spine_db_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"""

import os
from PySide6.QtWidgets import QMenu, QStatusBar, QToolButton
from PySide6.QtWidgets import QMenu, QStatusBar, QToolButton, QMessageBox
from PySide6.QtCore import Slot, QPoint
from PySide6.QtGui import QIcon, QFont
from .spine_db_editor import SpineDBEditor
Expand Down Expand Up @@ -46,7 +46,7 @@ def __init__(self, db_mngr, db_url_codenames=None):
self.statusBar().hide()
self.tab_load_success = True
if db_url_codenames is not None:
if not self.add_new_tab(db_url_codenames):
if not self.add_new_tab(db_url_codenames, window=True):
self.tab_load_success = False

def _make_other(self):
Expand Down Expand Up @@ -87,11 +87,28 @@ def _disconnect_tab_signals(self, index):
tab.ui.actionClose.triggered.disconnect(self.handle_close_request_from_tab)
return True

def _make_new_tab(self, db_url_codenames=None): # pylint: disable=arguments-differ
def _make_new_tab(self, db_url_codenames=None, window=False): # pylint: disable=arguments-differ
"""Makes a new tab, if successful return the tab, returns None otherwise"""
tab = SpineDBEditor(self.db_mngr)
if not tab.load_db_urls(db_url_codenames, create=True):
if not tab.load_db_urls(db_url_codenames, create=True, window=window):
return
# Checks if the same url is already opened under a different codename
for url, codename in db_url_codenames.items():
current_codename = codename
for db_map in self.db_mngr.db_maps:
is_same = str(url) == db_map.db_url
is_same = is_same and codename != db_map.codename
if is_same:
existing = db_map.codename
msg = QMessageBox(self.parent())
msg.setIcon(QMessageBox.Icon.Information)
msg.setWindowTitle(current_codename)
msg.setText(
f"<p>The same database is already open in another window. Opening the new window under "
f"the same name as the existing one: <b>{existing}</b></p>"
)
msg.exec()
break
return tab

def show_plus_button_context_menu(self, global_pos):
Expand Down
4 changes: 2 additions & 2 deletions spinetoolbox/spine_db_editor/widgets/spine_db_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def is_db_map_editor():
"""
return True

def load_db_urls(self, db_url_codenames, create=False, update_history=True):
def load_db_urls(self, db_url_codenames, create=False, update_history=True, window=False):
self.ui.actionImport.setEnabled(False)
self.ui.actionExport.setEnabled(False)
self.ui.actionMass_remove_items.setEnabled(False)
Expand All @@ -163,7 +163,7 @@ def load_db_urls(self, db_url_codenames, create=False, update_history=True):
self._changelog.clear()
self._purge_change_notifiers()
for url, codename in db_url_codenames.items():
db_map = self.db_mngr.get_db_map(url, self, codename=codename, create=create)
db_map = self.db_mngr.get_db_map(url, self, codename=codename, create=create, window=window)
if db_map is not None:
self.db_maps.append(db_map)
if not self.db_maps:
Expand Down
18 changes: 12 additions & 6 deletions spinetoolbox/spine_db_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,9 @@ def close_all_sessions(self):
for url in list(self._db_maps):
self.close_session(url)

def get_db_map(self, url, logger, ignore_version_error=False, codename=None, create=False, upgrade=False):
def get_db_map(
self, url, logger, ignore_version_error=False, codename=None, create=False, upgrade=False, window=False
):
"""Returns a DiffDatabaseMapping instance from url if possible, None otherwise.
If needed, asks the user to upgrade to the latest db version.
Expand All @@ -329,12 +331,13 @@ def get_db_map(self, url, logger, ignore_version_error=False, codename=None, cre
codename (str, NoneType, optional)
upgrade (bool, optional)
create (bool, optional)
window (bool, optional)
Returns:
DiffDatabaseMapping, NoneType
"""
try:
return self._do_get_db_map(url, codename, create, upgrade)
return self._do_get_db_map(url, codename, create, upgrade, window)
except SpineDBVersionError as v_err:
if ignore_version_error:
return None
Expand All @@ -350,7 +353,7 @@ def get_db_map(self, url, logger, ignore_version_error=False, codename=None, cre
ret = msg.exec() # Show message box
if ret == QMessageBox.StandardButton.Cancel:
return None
return self.get_db_map(url, logger, codename=codename, create=create, upgrade=True)
return self.get_db_map(url, logger, codename=codename, create=create, upgrade=True, window=window)
QMessageBox.information(
qApp.activeWindow(), # pylint: disable=undefined-variable
"Unsupported database version",
Expand All @@ -365,7 +368,7 @@ def get_db_map(self, url, logger, ignore_version_error=False, codename=None, cre
return None

@busy_effect
def _do_get_db_map(self, url, codename, create, upgrade):
def _do_get_db_map(self, url, codename, create, upgrade, window):
"""Returns a memorized DiffDatabaseMapping instance from url.
Called by `get_db_map`.
Expand All @@ -374,15 +377,18 @@ def _do_get_db_map(self, url, codename, create, upgrade):
codename (str, NoneType)
upgrade (bool)
create (bool)
window (bool)
Returns:
DiffDatabaseMapping
"""
url = str(url)
db_map = self._db_maps.get(url)
if db_map is not None:
if codename is not None:
db_map.codename = codename
if codename is not None and db_map.codename != codename:
if window: # If new editor window is being opened
return db_map
return None
return db_map
worker = SpineDBWorker(self, url, synchronous=self._synchronous)
try:
Expand Down
7 changes: 6 additions & 1 deletion tests/test_SpineDBManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,12 @@ def test_open_db_editor(self):
self._db_mngr.open_db_editor({self._db_url: "not_the_same"})
self.assertEqual(len(editors), 1)
editor = editors[0]
self.assertEqual(editor.tab_widget.count(), 2)
self.assertEqual(editor.tab_widget.count(), 1)
# Finally try to open the first tab again
self._db_mngr.open_db_editor({self._db_url: "test"})
editors = list(self._db_mngr.get_all_multi_spine_db_editors())
editor = editors[0]
self.assertEqual(editor.tab_widget.count(), 1)
for editor in self._db_mngr.get_all_multi_spine_db_editors():
QApplication.processEvents()
editor.close()
Expand Down

0 comments on commit 67d9b49

Please sign in to comment.