mirror of https://gitlab.com/openlp/openlp.git
Merge branch 'list-view' into 'master'
New Grid View for Theme Manager See merge request openlp/openlp!491
This commit is contained in:
commit
f22eafbeb8
|
@ -377,6 +377,7 @@ 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/theme manager view mode': 0,
|
||||
'user interface/show library': True,
|
||||
'user interface/show projectors': True,
|
||||
'user interface/show service': True,
|
||||
|
|
|
@ -337,3 +337,98 @@ def find_and_set_in_combo_box(combo_box, value_to_find, set_missing=True):
|
|||
# Not Found.
|
||||
index = 0 if set_missing else combo_box.currentIndex()
|
||||
combo_box.setCurrentIndex(index)
|
||||
|
||||
|
||||
class MultipleViewModeList(QtWidgets.QListWidget):
|
||||
"""
|
||||
An opinionated implementation of QListWidget that allows the list to use List View and
|
||||
Icon View.
|
||||
|
||||
:param parent:
|
||||
:param mode: The default mode of the list.
|
||||
"""
|
||||
def __init__(self, parent, mode=QtWidgets.QListWidget.ViewMode.ListMode):
|
||||
super().__init__(parent)
|
||||
self._view_mode_icon_size_list = None
|
||||
self._view_mode_icon_size_grid = None
|
||||
if mode == QtWidgets.QListWidget.ViewMode.IconMode:
|
||||
self.setViewMode(QtWidgets.QListWidget.ViewMode.IconMode)
|
||||
|
||||
def set_icon_size_by_view_mode(self, mode, size):
|
||||
"""
|
||||
Sets the preferred icon size by view mode.
|
||||
|
||||
:param mode: Desired mode to set the default size
|
||||
:param size: Default size for the provided mode
|
||||
"""
|
||||
if mode == QtWidgets.QListWidget.ViewMode.ListMode:
|
||||
self._view_mode_icon_size_list = size
|
||||
elif mode == QtWidgets.QListWidget.ViewMode.IconMode:
|
||||
self._view_mode_icon_size_grid = size
|
||||
if self.viewMode() == mode:
|
||||
self.setIconSize(size)
|
||||
|
||||
def setViewMode(self, mode):
|
||||
if mode is None:
|
||||
mode = QtWidgets.QListWidget.ViewMode.ListMode
|
||||
super().setViewMode(mode)
|
||||
if mode == QtWidgets.QListWidget.ViewMode.IconMode:
|
||||
if self._view_mode_icon_size_list is None:
|
||||
self._view_mode_icon_size_list = self.iconSize()
|
||||
if self._view_mode_icon_size_grid is not None:
|
||||
self.setIconSize(self._view_mode_icon_size_grid)
|
||||
self.setUniformItemSizes(True)
|
||||
self.setResizeMode(QtWidgets.QListWidget.ResizeMode.Adjust)
|
||||
self._on_resize_icon_mode()
|
||||
elif mode == QtWidgets.QListWidget.ViewMode.ListMode:
|
||||
if self._view_mode_icon_size_grid is None:
|
||||
self._view_mode_icon_size_grid = self.iconSize()
|
||||
if self._view_mode_icon_size_list is not None:
|
||||
self.setIconSize(self._view_mode_icon_size_list)
|
||||
self.setUniformItemSizes(False)
|
||||
self.setResizeMode(QtWidgets.QListWidget.ResizeMode.Fixed)
|
||||
self.setFlow(QtWidgets.QListWidget.Flow.TopToBottom)
|
||||
|
||||
def resizeEvent(self, event: QtGui.QResizeEvent):
|
||||
super().resizeEvent(event)
|
||||
self._on_resize_icon_mode()
|
||||
|
||||
def _on_resize_icon_mode(self):
|
||||
if self.viewMode() == QtWidgets.QListWidget.ViewMode.IconMode:
|
||||
size = self.size()
|
||||
iconHeight = self.iconSize().height()
|
||||
if size.height() < ((iconHeight + (iconHeight / 2))):
|
||||
if self.flow() != QtWidgets.QListWidget.Flow.TopToBottom:
|
||||
self.setFlow(QtWidgets.QListWidget.Flow.TopToBottom)
|
||||
elif self.flow() != QtWidgets.QListWidget.Flow.LeftToRight:
|
||||
self.setFlow(QtWidgets.QListWidget.Flow.LeftToRight)
|
||||
|
||||
|
||||
def set_list_view_mode_toolbar_state(toolbar, mode):
|
||||
"""
|
||||
Updates a OpenLPToolbar ListView button states after clicked
|
||||
|
||||
:param toolbar: OpenLPToolbar instance
|
||||
:param mode: New QListView mode
|
||||
"""
|
||||
if mode == QtWidgets.QListView.ViewMode.IconMode:
|
||||
toolbar.set_widget_checked('listView', False)
|
||||
toolbar.set_widget_checked('gridView', True)
|
||||
elif mode == QtWidgets.QListView.ViewMode.ListMode:
|
||||
toolbar.set_widget_checked('listView', True)
|
||||
toolbar.set_widget_checked('gridView', False)
|
||||
|
||||
|
||||
def add_list_view_mode_items_to_toolbar(toolbar, trigger_handler):
|
||||
toolbar.add_toolbar_action('listView',
|
||||
text=translate('OpenLP.Ui', 'List View'),
|
||||
icon=UiIcons().view_list,
|
||||
checked=False,
|
||||
tooltip=translate('OpenLP.Ui', 'Shows the list in a list view.'),
|
||||
triggers=trigger_handler.on_set_view_mode_list)
|
||||
toolbar.add_toolbar_action('gridView',
|
||||
text=translate('OpenLP.Ui', 'Grid View'),
|
||||
icon=UiIcons().view_grid,
|
||||
checked=False,
|
||||
tooltip=translate('OpenLP.Ui', 'Shows the list in a grid view.'),
|
||||
triggers=trigger_handler.on_set_view_mode_grid)
|
||||
|
|
|
@ -170,6 +170,8 @@ class UiIcons(metaclass=Singleton):
|
|||
'usermo': {'icon': 'op.users'},
|
||||
'users': {'icon': 'fa.users'},
|
||||
'video': {'icon': 'fa.file-video-o'},
|
||||
'view_list': {'icon': 'fa.th-list'},
|
||||
'view_grid': {'icon': 'fa.th-large'},
|
||||
'volunteer': {'icon': 'fa.group'}
|
||||
}
|
||||
self.load_icons(icon_list)
|
||||
|
|
|
@ -1340,6 +1340,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
|||
self.settings.setValue('user interface/live splitter geometry', self.live_controller.splitter.saveState())
|
||||
self.settings.setValue('user interface/preview splitter geometry', self.preview_controller.splitter.saveState())
|
||||
self.settings.setValue('user interface/main window splitter geometry', self.control_splitter.saveState())
|
||||
self.theme_manager.save_settings()
|
||||
|
||||
def update_recent_files_menu(self):
|
||||
"""
|
||||
|
|
|
@ -40,7 +40,8 @@ from openlp.core.common.utils import wait_for
|
|||
from openlp.core.lib import build_icon, check_item_selected, create_thumb, get_text_file_string, validate_thumb
|
||||
from openlp.core.lib.exceptions import ValidationError
|
||||
from openlp.core.lib.theme import Theme
|
||||
from openlp.core.lib.ui import create_widget_action, critical_error_message_box
|
||||
from openlp.core.lib.ui import MultipleViewModeList, add_list_view_mode_items_to_toolbar, create_widget_action, \
|
||||
critical_error_message_box, set_list_view_mode_toolbar_state
|
||||
from openlp.core.ui.filerenameform import FileRenameForm
|
||||
from openlp.core.ui.icons import UiIcons
|
||||
from openlp.core.ui.themeform import ThemeForm
|
||||
|
@ -92,13 +93,18 @@ class Ui_ThemeManager(object):
|
|||
icon=UiIcons().upload,
|
||||
tooltip=translate('OpenLP.ThemeManager', 'Export a theme.'),
|
||||
triggers=self.on_export_theme)
|
||||
self.toolbar.addSeparator()
|
||||
add_list_view_mode_items_to_toolbar(self.toolbar, self)
|
||||
self.layout.addWidget(self.toolbar)
|
||||
self.theme_widget = QtWidgets.QWidgetAction(self.toolbar)
|
||||
self.theme_widget.setObjectName('theme_widget')
|
||||
# create theme manager list
|
||||
self.theme_list_widget = QtWidgets.QListWidget(widget)
|
||||
self.theme_list_widget = MultipleViewModeList(widget)
|
||||
self.theme_list_widget.setAlternatingRowColors(True)
|
||||
self.theme_list_widget.setIconSize(QtCore.QSize(88, 50))
|
||||
self.theme_list_widget.set_icon_size_by_view_mode(QtWidgets.QListView.ViewMode.ListMode, QtCore.QSize(88, 50))
|
||||
self.theme_list_widget.set_icon_size_by_view_mode(QtWidgets.QListView.ViewMode.IconMode,
|
||||
QtCore.QSize(176, 100))
|
||||
self.theme_list_widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.theme_list_widget.setObjectName('theme_list_widget')
|
||||
self.layout.addWidget(self.theme_list_widget)
|
||||
|
@ -180,6 +186,7 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
|||
"""
|
||||
process the bootstrap post setup request
|
||||
"""
|
||||
self.load_settings()
|
||||
self.progress_form = ThemeProgressForm(self)
|
||||
self.theme_form = ThemeForm(self)
|
||||
self.theme_form.path = self.theme_path
|
||||
|
@ -187,6 +194,20 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
|||
self.upgrade_themes() # TODO: Can be removed when upgrade path from OpenLP 2.4 no longer needed
|
||||
self.load_themes()
|
||||
|
||||
def load_settings(self):
|
||||
view_mode_value = None
|
||||
try:
|
||||
view_mode_value = self.settings.value('user interface/theme manager view mode')
|
||||
self.theme_list_widget.setViewMode(view_mode_value)
|
||||
except Exception:
|
||||
view_mode_value = QtWidgets.QListWidget.ViewMode.ListMode
|
||||
self.settings.setValue('user interface/theme manager view mode', view_mode_value)
|
||||
set_list_view_mode_toolbar_state(self.toolbar, view_mode_value)
|
||||
|
||||
def save_settings(self):
|
||||
if self.theme_list_widget:
|
||||
self.settings.setValue('user interface/theme manager view mode', self.theme_list_widget.viewMode())
|
||||
|
||||
def screen_changed(self):
|
||||
"""
|
||||
Update the default theme location and size for when screen size changed
|
||||
|
@ -278,6 +299,16 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
|||
self.delete_toolbar_action.setVisible(item not in self.theme_list_widget.selectedItems())
|
||||
Registry().execute('theme_change_global')
|
||||
|
||||
def on_set_view_mode_list(self):
|
||||
mode = QtWidgets.QListView.ViewMode.ListMode
|
||||
self.theme_list_widget.setViewMode(mode)
|
||||
set_list_view_mode_toolbar_state(self.toolbar, mode)
|
||||
|
||||
def on_set_view_mode_grid(self):
|
||||
mode = QtWidgets.QListView.ViewMode.IconMode
|
||||
self.theme_list_widget.setViewMode(mode)
|
||||
set_list_view_mode_toolbar_state(self.toolbar, mode)
|
||||
|
||||
def on_theme_level_updated(self):
|
||||
"""
|
||||
Update the theme level, called from web controller.
|
||||
|
|
|
@ -95,6 +95,25 @@ class OpenLPToolbar(QtWidgets.QToolBar):
|
|||
else:
|
||||
log.warning('No handle "%s" in actions list.', str(handle))
|
||||
|
||||
def set_widget_checked(self, widgets, checked=True):
|
||||
"""
|
||||
Set the checked state for a widget or a list of widgets.
|
||||
|
||||
:param widgets: A list of string with widget object names.
|
||||
:param enabled: The new state as bool.
|
||||
"""
|
||||
if isinstance(widgets, list):
|
||||
for handle in widgets:
|
||||
if handle in self.actions:
|
||||
self.actions[handle].setChecked(checked)
|
||||
else:
|
||||
log.warning('No handle "%s" in actions list.', str(handle))
|
||||
else:
|
||||
if widgets in self.actions:
|
||||
self.actions[widgets].setChecked(checked)
|
||||
else:
|
||||
log.warning('No handle "%s" in actions list.', str(widgets))
|
||||
|
||||
def remove_widget(self, name):
|
||||
"""
|
||||
Find and remove an action from the toolbar
|
||||
|
|
|
@ -26,9 +26,11 @@ from unittest.mock import MagicMock, call, patch
|
|||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
from openlp.core.common.i18n import UiStrings, translate
|
||||
from openlp.core.lib.ui import add_welcome_page, create_action, create_button, create_button_box, \
|
||||
create_horizontal_adjusting_combo_box, create_valign_selection_widgets, create_widget_action, \
|
||||
critical_error_message_box, find_and_set_in_combo_box, set_case_insensitive_completer
|
||||
from openlp.core.lib.ui import MultipleViewModeList, add_list_view_mode_items_to_toolbar, add_welcome_page, \
|
||||
create_action, create_button, create_button_box, create_horizontal_adjusting_combo_box, \
|
||||
create_valign_selection_widgets, create_widget_action, critical_error_message_box, find_and_set_in_combo_box, \
|
||||
set_case_insensitive_completer, set_list_view_mode_toolbar_state
|
||||
from openlp.core.widgets.toolbar import OpenLPToolbar
|
||||
|
||||
|
||||
def test_add_welcome_page():
|
||||
|
@ -341,3 +343,148 @@ def test_set_case_insensitive_completer():
|
|||
completer = line_edit.completer()
|
||||
assert isinstance(completer, QtWidgets.QCompleter)
|
||||
assert completer.caseSensitivity() == QtCore.Qt.CaseInsensitive
|
||||
|
||||
|
||||
def test_multiple_view_mode_list(settings):
|
||||
"""
|
||||
Tests if MultipleViewModeList works and have the default ViewMode
|
||||
"""
|
||||
# GIVEN: MultipleViewModeList
|
||||
|
||||
# WHEN: It's built
|
||||
list = MultipleViewModeList(None)
|
||||
|
||||
# THEN: It's should be build sucessfully, with default ListMode
|
||||
list.viewMode() == QtWidgets.QListWidget.ViewMode.ListMode
|
||||
|
||||
|
||||
def test_multiple_view_mode_list_set_icon_size_by_view_mode_icon_mode(settings):
|
||||
"""
|
||||
Tests if MultipleViewModeList's set_icon_size_by_view_mode works with a IconMode default value
|
||||
"""
|
||||
# GIVEN: a MultipleViewModeList instance and a custom icon size
|
||||
list = MultipleViewModeList(None)
|
||||
icon_size = QtCore.QSize(93, 37)
|
||||
|
||||
# WHEN: set_icon_size_by_view_mode is called with IconMode and mode is changed
|
||||
list.set_icon_size_by_view_mode(QtWidgets.QListWidget.ViewMode.IconMode, icon_size)
|
||||
list.setViewMode(QtWidgets.QListWidget.ViewMode.IconMode)
|
||||
|
||||
# THEN: New icon size should be set successfully
|
||||
assert list.iconSize() == icon_size
|
||||
|
||||
|
||||
def test_multiple_view_mode_list_set_icon_size_by_view_mode_list_mode(settings):
|
||||
"""
|
||||
Tests if MultipleViewModeList's set_icon_size_by_view_mode works with a ListMode default value
|
||||
"""
|
||||
# GIVEN: a MultipleViewModeList instance and a custom icon size
|
||||
list = MultipleViewModeList(None, QtWidgets.QListWidget.ViewMode.IconMode)
|
||||
icon_size = QtCore.QSize(93, 37)
|
||||
|
||||
# WHEN: set_icon_size_by_view_mode is called with ListMode and mode is changed
|
||||
list.set_icon_size_by_view_mode(QtWidgets.QListWidget.ViewMode.ListMode, icon_size)
|
||||
list.setViewMode(QtWidgets.QListWidget.ViewMode.ListMode)
|
||||
|
||||
# THEN: New icon size should be set successfully
|
||||
assert list.iconSize() == icon_size
|
||||
|
||||
|
||||
def test_multiple_view_mode_list_set_icon_size_by_view_mode_changes_current_size(settings):
|
||||
"""
|
||||
Tests if MultipleViewModeList's set_icon_size_by_view_mode changes the current value if provided mode is the same
|
||||
as current List's ViewMode.
|
||||
"""
|
||||
# GIVEN: a MultipleViewModeList instance and a custom icon size
|
||||
list = MultipleViewModeList(None, QtWidgets.QListWidget.ViewMode.IconMode)
|
||||
icon_size = QtCore.QSize(93, 37)
|
||||
|
||||
# WHEN: set_icon_size_by_view_mode is called with IconMode and mode is changed
|
||||
list.set_icon_size_by_view_mode(QtWidgets.QListWidget.ViewMode.IconMode, icon_size)
|
||||
|
||||
# THEN: New icon size should be set successfully
|
||||
assert list.iconSize() == icon_size
|
||||
|
||||
|
||||
def test_multiple_view_mode_list_set_view_mode_preserves_last_icon_size(settings):
|
||||
"""
|
||||
Tests if MultipleViewModeList's preserves the last iconSize when no equivalent
|
||||
default icon size is present
|
||||
"""
|
||||
# GIVEN: a MultipleViewModeList instance and a custom icon size
|
||||
list = MultipleViewModeList(None, QtWidgets.QListWidget.ViewMode.IconMode)
|
||||
icon_size = QtCore.QSize(93, 37)
|
||||
last_icon_size = list.iconSize()
|
||||
list.set_icon_size_by_view_mode(QtWidgets.QListWidget.ViewMode.ListMode, icon_size)
|
||||
|
||||
# WHEN: viewMode() is changed and reverted
|
||||
list.setViewMode(QtWidgets.QListWidget.ViewMode.ListMode)
|
||||
list.setViewMode(QtWidgets.QListWidget.ViewMode.IconMode)
|
||||
|
||||
# THEN: Old icon size should be restored
|
||||
assert list.iconSize() == last_icon_size
|
||||
|
||||
|
||||
def test_add_list_view_mode_items_to_toolbar_creates_items(settings):
|
||||
"""
|
||||
Tests if add_list_view_mode_items_to_toolbar creates the list view items.
|
||||
"""
|
||||
# GIVEN: an OpenLPToolbar
|
||||
toolbar = OpenLPToolbar(None)
|
||||
|
||||
# WHEN: add_list_view_mode_items_to_toolbar is called
|
||||
add_list_view_mode_items_to_toolbar(toolbar, MagicMock())
|
||||
|
||||
# THEN: Assert correct icons are created
|
||||
assert isinstance(toolbar.actions['listView'], QtWidgets.QAction) is True
|
||||
assert isinstance(toolbar.actions['gridView'], QtWidgets.QAction) is True
|
||||
|
||||
|
||||
def test_add_list_view_mode_items_to_toolbar_click_calls_handlers(settings):
|
||||
"""
|
||||
Tests if add_list_view_mode_items_to_toolbar created items calls the handlers
|
||||
"""
|
||||
# GIVEN: an OpenLPToolbar with ListView items
|
||||
toolbar = OpenLPToolbar(None)
|
||||
handler = MagicMock()
|
||||
add_list_view_mode_items_to_toolbar(toolbar, handler)
|
||||
|
||||
# WHEN: handler items is called
|
||||
toolbar.actions['listView'].trigger()
|
||||
toolbar.actions['gridView'].trigger()
|
||||
|
||||
# THEN: Assert correct handlers were called
|
||||
handler.on_set_view_mode_list.assert_called_once()
|
||||
handler.on_set_view_mode_grid.assert_called_once()
|
||||
|
||||
|
||||
def test_set_list_view_mode_toolbar_state_view_mode_list_mode(settings):
|
||||
"""
|
||||
Tests if set_list_view_mode_toolbar_state changes the toolbar items state to List Mode correctly
|
||||
"""
|
||||
# GIVEN: an OpenLPToolbar with checkable List View items
|
||||
toolbar = OpenLPToolbar(None)
|
||||
add_list_view_mode_items_to_toolbar(toolbar, MagicMock())
|
||||
|
||||
# WHEN: set_list_view_mode_toolbar_state is called with ListMode
|
||||
set_list_view_mode_toolbar_state(toolbar, QtWidgets.QListWidget.ViewMode.ListMode)
|
||||
|
||||
# THEN: Assert correct icons are checked or not
|
||||
assert toolbar.actions['listView'].isChecked() is True
|
||||
assert toolbar.actions['gridView'].isChecked() is False
|
||||
|
||||
|
||||
def test_set_list_view_mode_toolbar_state_view_mode_icon_mode(settings):
|
||||
"""
|
||||
Tests if set_list_view_mode_toolbar_state changes the toolbar items state to Grid Mode correctly
|
||||
"""
|
||||
# GIVEN: an OpenLPToolbar with checkable List View items
|
||||
toolbar = OpenLPToolbar(None)
|
||||
add_list_view_mode_items_to_toolbar(toolbar, MagicMock())
|
||||
|
||||
# WHEN: set_list_view_mode_toolbar_state is called with ListMode
|
||||
set_list_view_mode_toolbar_state(toolbar, QtWidgets.QListWidget.ViewMode.IconMode)
|
||||
|
||||
# THEN: Assert correct icons are checked or not
|
||||
assert toolbar.actions['listView'].isChecked() is False
|
||||
assert toolbar.actions['gridView'].isChecked() is True
|
||||
|
|
|
@ -492,6 +492,7 @@ def test_bootstrap_post(mocked_rename_form, mocked_theme_form, theme_manager):
|
|||
Test the functions of bootstrap_post_setup are called.
|
||||
"""
|
||||
# GIVEN:
|
||||
theme_manager.toolbar = MagicMock()
|
||||
theme_manager.theme_path = MagicMock()
|
||||
theme_manager.load_themes = MagicMock()
|
||||
theme_manager.upgrade_themes = MagicMock()
|
||||
|
|
Loading…
Reference in New Issue