Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions dev/tests/test_tab_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,20 @@
class ParentWindow(QWidget):
def __init__(self):
super().__init__()


class FakeFileManager:
def __init__(self):
self.saved = 0
self.saved_as = 0

def action_save(self):
def save_file(self, file_path, content):
self.saved += 1
return True

def save_file_as(self, content, parent=None):
self.saved_as += 1
return "/fake/saved.py"


class FakeSignal:
Expand Down Expand Up @@ -50,6 +60,9 @@ def display_name(self):
def setText(self, text):
self._text = text

def text(self):
return self._text

def setModified(self, modified):
self._modified = modified

Expand All @@ -65,7 +78,7 @@ def make_settings(tmp_path):
def test_tab_manager_creates_deduplicates_titles_and_paths(qapp, tmp_path):
settings = make_settings(tmp_path)
parent = ParentWindow()
tabs = TabManager(settings, parent)
tabs = TabManager(settings, parent=parent)
changed = []
tabs.tab_changed.connect(changed.append)

Expand Down Expand Up @@ -99,7 +112,8 @@ def test_close_tab_prompt_save_discard_cancel_and_close_all(monkeypatch, qapp, t
monkeypatch.setattr(tab_module, "CodeEditor", FakeTabEditor)
settings = make_settings(tmp_path)
parent = ParentWindow()
tabs = TabManager(settings, parent)
fake_fm = FakeFileManager()
tabs = TabManager(settings, fake_fm, parent)

first = tabs.new_tab(str(tmp_path / "first.py"), "print(1)\n")
first.setModified(True)
Expand All @@ -117,7 +131,7 @@ def test_close_tab_prompt_save_discard_cancel_and_close_all(monkeypatch, qapp, t
lambda *args, **kwargs: QMessageBox.StandardButton.Save,
)
assert tabs.close_tab(tabs.indexOf(first)) is True
assert parent.saved == 1
assert fake_fm.saved == 1

second = tabs.new_tab(str(tmp_path / "second.py"), "print(2)\n")
third = tabs.new_tab(str(tmp_path / "third.py"), "print(3)\n")
Expand All @@ -139,7 +153,8 @@ def test_prompt_save_all_respects_cancel_and_save(monkeypatch, qapp, tmp_path):
monkeypatch.setattr(tab_module, "CodeEditor", FakeTabEditor)
settings = make_settings(tmp_path)
parent = ParentWindow()
tabs = TabManager(settings, parent)
fake_fm = FakeFileManager()
tabs = TabManager(settings, fake_fm, parent)
editor = tabs.new_tab(str(tmp_path / "dirty.py"), "print('dirty')\n")
editor.setModified(True)

Expand All @@ -157,7 +172,7 @@ def test_prompt_save_all_respects_cancel_and_save(monkeypatch, qapp, tmp_path):
lambda *args, **kwargs: QMessageBox.StandardButton.Save,
)
assert tabs.prompt_save_all() is True
assert parent.saved == 1
assert fake_fm.saved == 1

tabs.deleteLater()
parent.deleteLater()
Expand All @@ -166,7 +181,7 @@ def test_prompt_save_all_respects_cancel_and_save(monkeypatch, qapp, tmp_path):
def test_welcome_tab_reuse_theme_update_close_and_template_signal(qapp, tmp_path):
settings = make_settings(tmp_path)
parent = ParentWindow()
tabs = TabManager(settings, parent)
tabs = TabManager(settings, parent=parent)

welcome = tabs.show_welcome_tab("default_dark", "dark", "#2F7A44")
same = tabs.show_welcome_tab("custom", "light", "#336699")
Expand Down Expand Up @@ -202,7 +217,7 @@ def test_deferred_close_button_closes_editor_on_next_event_loop(monkeypatch, qap
)
settings = make_settings(tmp_path)
parent = ParentWindow()
tabs = TabManager(settings, parent)
tabs = TabManager(settings, parent=parent)
editor = tabs.new_tab(str(tmp_path / "deferred.py"), "print('x')\n")

tabs._close_editor_tab(editor)
Expand Down
2 changes: 1 addition & 1 deletion meadowpy/ui/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def showEvent(self, event) -> None: # noqa: N802
def _create_tab_manager(self) -> None:
from PyQt6.QtWidgets import QFrame, QVBoxLayout

self._tab_manager = TabManager(self._settings, self)
self._tab_manager = TabManager(self._settings, self._file_manager, self)

# Wrap the editor in a styled container so it picks up the same
# rounded-bottom-corner border treatment as the surrounding panels.
Expand Down
23 changes: 16 additions & 7 deletions meadowpy/ui/tab_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,10 @@ class TabManager(QTabWidget):

tab_changed = pyqtSignal(object) # emits CodeEditor or None

def __init__(self, settings: Settings, parent=None):
def __init__(self, settings: Settings, file_manager=None, parent=None):
super().__init__(parent)
self._settings = settings
self._file_manager = file_manager
self._untitled_counter = 1

self.setObjectName("editorTabs")
Expand Down Expand Up @@ -254,9 +255,13 @@ def close_tab(self, index: int) -> bool:
if reply == QMessageBox.StandardButton.Cancel:
return False
if reply == QMessageBox.StandardButton.Save:
main_window = self.parent()
if hasattr(main_window, "action_save"):
main_window.action_save()
if self._file_manager:
if editor.file_path:
self._file_manager.save_file(editor.file_path, editor.text())
else:
path = self._file_manager.save_file_as(editor.text(), parent=self)
if not path:
return False
self.removeTab(index)
return True

Expand All @@ -283,9 +288,13 @@ def prompt_save_all(self) -> bool:
if reply == QMessageBox.StandardButton.Cancel:
return False
if reply == QMessageBox.StandardButton.Save:
main_window = self.parent()
if hasattr(main_window, "action_save"):
main_window.action_save()
if self._file_manager:
if editor.file_path:
self._file_manager.save_file(editor.file_path, editor.text())
else:
path = self._file_manager.save_file_as(editor.text(), parent=self)
if not path:
return False
return True

def current_editor(self) -> CodeEditor | None:
Expand Down