Merge branch 'issue-1161' into 'master'

Fix #1161 by saving and loading the state of individual docks

Closes #1161

See merge request openlp/openlp!497
This commit is contained in:
Raoul Snyman 2022-10-21 05:56:48 +00:00
commit c6ba6fe0c8
3 changed files with 110 additions and 23 deletions

View File

@ -365,6 +365,7 @@ class Settings(QtCore.QSettings):
'themes/theme level': ThemeLevel.Global,
'themes/item transitions': False,
'themes/hot reload': False,
'user interface/is preset layout': False,
'user interface/live panel': True,
'user interface/live splitter geometry': QtCore.QByteArray(),
'user interface/lock panel': True,
@ -374,7 +375,10 @@ class Settings(QtCore.QSettings):
'user interface/main window state': QtCore.QByteArray(),
'user interface/preview panel': True,
'user interface/preview splitter geometry': QtCore.QByteArray(),
'user interface/is preset layout': False,
'user interface/show library': True,
'user interface/show projectors': True,
'user interface/show service': True,
'user interface/show themes': True,
'projector/show after wizard': False,
'projector/db type': 'sqlite',
'projector/db username': '',

View File

@ -277,7 +277,7 @@ class Ui_MainWindow(object):
self.settings_configure_item = create_action(main_window, 'settingsConfigureItem',
icon=UiIcons().settings, can_shortcuts=True,
category=UiStrings().Settings)
# Give QT Extra Hint that this is the Preferences Menu Item
# Give Qt Extra Hint that this is the Preferences Menu Item
self.settings_configure_item.setMenuRole(QtWidgets.QAction.PreferencesRole)
self.settings_import_item = create_action(main_window, 'settingsImportItem',
category=UiStrings().Import, can_shortcuts=True)
@ -287,7 +287,7 @@ class Ui_MainWindow(object):
self.about_item = create_action(main_window, 'aboutItem', icon=UiIcons().info,
can_shortcuts=True, category=UiStrings().Help,
triggers=self.on_about_item_clicked)
# Give QT Extra Hint that this is an About Menu Item
# Give Qt Extra Hint that this is an About Menu Item
self.about_item.setMenuRole(QtWidgets.QAction.AboutRole)
if is_win():
self.local_help_file = AppLocation.get_directory(AppLocation.AppDir) / 'OpenLP.chm'
@ -495,10 +495,10 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
self.update_recent_files_menu()
self.plugin_form = PluginForm(self)
# Set up signals and slots
self.media_manager_dock.visibilityChanged.connect(self.view_media_manager_item.setChecked)
self.service_manager_dock.visibilityChanged.connect(self.view_service_manager_item.setChecked)
self.theme_manager_dock.visibilityChanged.connect(self.view_theme_manager_item.setChecked)
self.projector_manager_dock.visibilityChanged.connect(self.view_projector_manager_item.setChecked)
self.media_manager_dock.visibilityChanged.connect(self.toggle_media_manager)
self.service_manager_dock.visibilityChanged.connect(self.toggle_service_manager)
self.theme_manager_dock.visibilityChanged.connect(self.toggle_theme_manager)
self.projector_manager_dock.visibilityChanged.connect(self.toggle_projector_manager)
self.import_theme_item.triggered.connect(self.theme_manager_contents.on_import_theme)
self.export_theme_item.triggered.connect(self.theme_manager_contents.on_export_theme)
self.web_site_item.triggered.connect(self.on_help_web_site_clicked)
@ -661,10 +661,14 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
self.set_view_mode(False, True, False, False, True, True)
self.mode_live_item.setChecked(True)
else:
self.set_view_mode(True, True, True,
self.settings.value('user interface/preview panel'),
self.settings.value('user interface/live panel'),
True)
self.set_view_mode(
self.settings.value('user interface/show library'),
self.settings.value('user interface/show service'),
self.settings.value('user interface/show themes'),
self.settings.value('user interface/preview panel'),
self.settings.value('user interface/live panel'),
self.settings.value('user interface/show projectors')
)
def first_time(self):
"""
@ -1154,15 +1158,21 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
"""
Toggle the visibility of the media manager
"""
self.media_manager_dock.setVisible(not self.media_manager_dock.isVisible())
if self.sender() is self.view_media_manager_item:
self.media_manager_dock.setVisible(not self.media_manager_dock.isVisible())
self.view_media_manager_item.setChecked(self.media_manager_dock.isVisible())
self.settings.setValue('user interface/is preset layout', False)
self.settings.setValue('user interface/show library', self.media_manager_dock.isVisible())
def toggle_projector_manager(self):
"""
Toggle visibility of the projector manager
"""
self.projector_manager_dock.setVisible(not self.projector_manager_dock.isVisible())
if self.sender() is self.view_projector_manager_item:
self.projector_manager_dock.setVisible(not self.projector_manager_dock.isVisible())
self.view_projector_manager_item.setChecked(self.projector_manager_dock.isVisible())
self.settings.setValue('user interface/is preset layout', False)
self.settings.setValue('user interface/show projectors', self.projector_manager_dock.isVisible())
# Check/uncheck checkbox on First time wizard based on visibility of this panel.
if not self.settings.value('projector/show after wizard'):
self.settings.setValue('projector/show after wizard', True)
@ -1173,15 +1183,21 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
"""
Toggle the visibility of the service manager
"""
self.service_manager_dock.setVisible(not self.service_manager_dock.isVisible())
if self.sender() is self.view_service_manager_item:
self.service_manager_dock.setVisible(not self.service_manager_dock.isVisible())
self.view_service_manager_item.setChecked(self.service_manager_dock.isVisible())
self.settings.setValue('user interface/is preset layout', False)
self.settings.setValue('user interface/show service', self.service_manager_dock.isVisible())
def toggle_theme_manager(self):
"""
Toggle the visibility of the theme manager
"""
self.theme_manager_dock.setVisible(not self.theme_manager_dock.isVisible())
if self.sender() is self.view_theme_manager_item:
self.theme_manager_dock.setVisible(not self.theme_manager_dock.isVisible())
self.view_theme_manager_item.setChecked(self.theme_manager_dock.isVisible())
self.settings.setValue('user interface/is preset layout', False)
self.settings.setValue('user interface/show themes', self.theme_manager_dock.isVisible())
def set_preview_panel_visibility(self, visible):
"""

View File

@ -72,6 +72,7 @@ def main_window(state, settings, mocked_qapp):
mocked_qapp.primaryScreen.return_value = mocked_screen
ScreenList.create(mocked_qapp)
mainwindow = MainWindow()
mainwindow.activateWindow = MagicMock()
yield mainwindow
del mainwindow
renderer_patcher.stop()
@ -579,8 +580,63 @@ def test_projector_manager_dock_unlocked(main_window_reduced):
projector_dock.setFeatures.assert_called_with(7)
@patch('openlp.core.ui.mainwindow.MainWindow.open_cmd_line_files')
@patch('openlp.core.ui.mainwindow.MainWindow.set_view_mode')
def test_load_settings_view_mode_default_mode(mocked_view_mode, main_window, settings):
def test_show_cmd_line_args(mocked_view_mode, mocked_open_cmd_line_files, main_window, settings):
"""Test that command line arguments are loaded on show"""
# GIVEN: A newly opened OpenLP instance with some command line arguments
main_window.application.args = ['-disable-web-security', 'new_file_name.osz']
# WHEN: MainWindow.show() is called
main_window.show()
# THEN: The command line arguments are searched for a file name
mocked_open_cmd_line_files.assert_called_once_with(main_window.application.args)
@patch('openlp.core.ui.mainwindow.MainWindow.set_view_mode')
def test_show_load_last_file(mocked_view_mode, main_window, settings):
"""Test that the last file opened is loaded on show"""
# GIVEN: A newly opened OpenLP instance with some command line arguments
main_window.service_manager_contents.load_last_file = MagicMock()
main_window.settings.setValue('core/auto open', True)
# WHEN: MainWindow.show() is called
main_window.show()
# THEN: The command line arguments are searched for a file name
main_window.service_manager_contents.load_last_file.assert_called_once_with()
@patch('openlp.core.ui.mainwindow.MainWindow.set_view_mode')
def test_load_settings_custom_layout(mocked_view_mode, main_window, settings):
"""Test that the view mode is called with the correct parameters for default mode"""
# GIVEN a newly opened OpenLP instance, mocked screens and settings for a valid window position
# mock out some other calls in load_settings()
main_window.control_splitter = MagicMock()
main_window._live_controller = MagicMock()
main_window._preview_controller = MagicMock()
main_window.activateWindow = MagicMock()
main_window.settings.setValue('core/view mode', 'default')
main_window.settings.setValue('user interface/is preset layout', False)
main_window.settings.setValue('user interface/show library', True)
main_window.settings.setValue('user interface/show service', False)
main_window.settings.setValue('user interface/show themes', True)
main_window.settings.setValue('user interface/show projectors', False)
main_window.settings.setValue('user interface/live panel', True)
main_window.settings.setValue('user interface/preview panel', False)
# WHEN: we call to show method
main_window.show()
# THEN:
# The default mode should have been called.
mocked_view_mode.assert_called_with(True, True, True, False, True, False)
@patch('openlp.core.ui.mainwindow.QtWidgets.QWidget.show')
@patch('openlp.core.ui.mainwindow.MainWindow.set_view_mode')
def test_load_settings_view_mode_default_mode(mocked_view_mode, mocked_show, main_window, settings):
"""
Test that the view mode is called with the correct parameters for default mode
"""
@ -589,10 +645,11 @@ def test_load_settings_view_mode_default_mode(mocked_view_mode, main_window, set
main_window.control_splitter = MagicMock()
main_window._live_controller = MagicMock()
main_window._preview_controller = MagicMock()
main_window.activateWindow = MagicMock()
main_window.settings.setValue('core/view mode', 'default')
main_window.settings.setValue('user interface/is preset layout', True)
# WHENL we call to show method
# WHEN: we call to show method
main_window.show()
# THEN:
@ -600,10 +657,14 @@ def test_load_settings_view_mode_default_mode(mocked_view_mode, main_window, set
mocked_view_mode.assert_called_with(True, True, True, True, True, True)
@patch('openlp.core.ui.mainwindow.QtWidgets.QWidget.show')
@patch('openlp.core.ui.mainwindow.MainWindow.set_view_mode')
def test_load_settings_view_mode_setup_mode(mocked_view_mode, main_window, settings):
def test_load_settings_view_mode_setup_mode(mocked_view_mode, mocked_show, main_window, settings):
"""
Test that the view mode is called with the correct parameters for setup mode
Note: for some reason, only when the test is running, the QWidget.show() method resets the layout setting,
so this is mocked out to prevent it from interferring in the loading of the view layout
"""
# GIVEN a newly opened OpenLP instance, mocked screens and settings for a valid window position
# mock out some other calls in load_settings()
@ -613,7 +674,7 @@ def test_load_settings_view_mode_setup_mode(mocked_view_mode, main_window, setti
main_window.settings.setValue('core/view mode', 'setup')
main_window.settings.setValue('user interface/is preset layout', True)
# WHENL we call to show method
# WHEN: we call to show method
main_window.show()
# THEN:
@ -621,10 +682,14 @@ def test_load_settings_view_mode_setup_mode(mocked_view_mode, main_window, setti
mocked_view_mode.assert_called_with(True, True, False, True, False, True)
@patch('openlp.core.ui.mainwindow.QtWidgets.QWidget.show')
@patch('openlp.core.ui.mainwindow.MainWindow.set_view_mode')
def test_load_settings_view_mode_live_mode(mocked_view_mode, main_window, settings):
def test_load_settings_view_mode_live_mode(mocked_view_mode, mocked_show, main_window, settings):
"""
Test that the view mode is called with the correct parameters for live mode
Note: for some reason, only when the test is running, the QWidget.show() method resets the layout setting,
so this is mocked out to prevent it from interferring in the loading of the view layout
"""
# GIVEN a newly opened OpenLP instance, mocked screens and settings for a valid window position
# mock out some other calls in load_settings()
@ -634,7 +699,7 @@ def test_load_settings_view_mode_live_mode(mocked_view_mode, main_window, settin
main_window.settings.setValue('core/view mode', 'live')
main_window.settings.setValue('user interface/is preset layout', True)
# WHENL we call to show method
# WHEN: we call to show method
main_window.show()
# THEN:
@ -652,11 +717,12 @@ def test_load_settings_view_mode_preview(mocked_view_mode, main_window, settings
main_window.control_splitter = MagicMock()
main_window._live_controller = MagicMock()
main_window._preview_controller = MagicMock()
main_window.activateWindow = MagicMock()
main_window.settings.setValue('core/view mode', 'default')
main_window.settings.setValue('user interface/is preset layout', False)
main_window.settings.setValue('user interface/preview panel', False)
# WHENL we call to show method
# WHEN: we call to show method
main_window.show()
# THEN:
@ -674,11 +740,12 @@ def test_load_settings_view_mode_live(mocked_view_mode, main_window, settings):
main_window.control_splitter = MagicMock()
main_window._live_controller = MagicMock()
main_window._preview_controller = MagicMock()
main_window.activateWindow = MagicMock()
main_window.settings.setValue('core/view mode', 'default')
main_window.settings.setValue('user interface/is preset layout', False)
main_window.settings.setValue('user interface/live panel', False)
# WHENL we call to show method
# WHEN: we call to show method
main_window.show()
# THEN: