[fix #1385438] Make list widget items select tab pages via user data rather than just their position.

bzr-revno: 2429
Fixes: https://launchpad.net/bugs/1385438
This commit is contained in:
Raoul Snyman 2014-10-25 23:04:20 +02:00
commit 0a1897f1da
5 changed files with 149 additions and 25 deletions

View File

@ -62,7 +62,6 @@ class Ui_SettingsDialog(object):
self.button_box = create_button_box(settings_dialog, 'button_box', ['cancel', 'ok']) self.button_box = create_button_box(settings_dialog, 'button_box', ['cancel', 'ok'])
self.dialog_layout.addWidget(self.button_box, 1, 1, 1, 1) self.dialog_layout.addWidget(self.button_box, 1, 1, 1, 1)
self.retranslateUi(settings_dialog) self.retranslateUi(settings_dialog)
self.setting_list_widget.currentRowChanged.connect(self.tab_changed)
def retranslateUi(self, settings_dialog): def retranslateUi(self, settings_dialog):
""" """

View File

@ -31,10 +31,10 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings
""" """
import logging import logging
from PyQt4 import QtGui from PyQt4 import QtCore, QtGui
from openlp.core.common import Registry, RegistryProperties from openlp.core.common import Registry, RegistryProperties
from openlp.core.lib import PluginStatus, build_icon from openlp.core.lib import build_icon
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
from openlp.core.ui.media import PlayerTab from openlp.core.ui.media import PlayerTab
from .settingsdialog import Ui_SettingsDialog from .settingsdialog import Ui_SettingsDialog
@ -55,6 +55,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog, RegistryProperties):
super(SettingsForm, self).__init__(parent) super(SettingsForm, self).__init__(parent)
self.processes = [] self.processes = []
self.setupUi(self) self.setupUi(self)
self.setting_list_widget.currentRowChanged.connect(self.list_item_changed)
def exec_(self): def exec_(self):
""" """
@ -65,33 +66,30 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog, RegistryProperties):
while self.stacked_layout.count(): while self.stacked_layout.count():
# take at 0 and the rest shuffle up. # take at 0 and the rest shuffle up.
self.stacked_layout.takeAt(0) self.stacked_layout.takeAt(0)
self.insert_tab(self.general_tab, 0, PluginStatus.Active) self.insert_tab(self.general_tab)
self.insert_tab(self.themes_tab, 1, PluginStatus.Active) self.insert_tab(self.themes_tab)
self.insert_tab(self.advanced_tab, 2, PluginStatus.Active) self.insert_tab(self.advanced_tab)
self.insert_tab(self.player_tab, 3, PluginStatus.Active) self.insert_tab(self.player_tab)
count = 4
for plugin in self.plugin_manager.plugins: for plugin in self.plugin_manager.plugins:
if plugin.settings_tab: if plugin.settings_tab:
self.insert_tab(plugin.settings_tab, count, plugin.status) self.insert_tab(plugin.settings_tab, plugin.is_active())
count += 1
self.setting_list_widget.setCurrentRow(0) self.setting_list_widget.setCurrentRow(0)
return QtGui.QDialog.exec_(self) return QtGui.QDialog.exec_(self)
def insert_tab(self, tab, location, is_active): def insert_tab(self, tab_widget, is_visible=True):
""" """
Add a tab to the form at a specific location Add a tab to the form at a specific location
:param tab_widget: The widget to add
:param is_visible: If this tab should be visible
""" """
log.debug('Inserting %s tab' % tab.tab_title) log.debug('Inserting %s tab' % tab_widget.tab_title)
# add the tab to get it to display in the correct part of the screen # add the tab to get it to display in the correct part of the screen
pos = self.stacked_layout.addWidget(tab) self.stacked_layout.addWidget(tab_widget)
if is_active: if is_visible:
item_name = QtGui.QListWidgetItem(tab.tab_title_visible) list_item = QtGui.QListWidgetItem(build_icon(tab_widget.icon_path), tab_widget.tab_title_visible)
icon = build_icon(tab.icon_path) list_item.setData(QtCore.Qt.UserRole, tab_widget.tab_title)
item_name.setIcon(icon) self.setting_list_widget.addItem(list_item)
self.setting_list_widget.insertItem(location, item_name)
else:
# then remove tab to stop the UI displaying it even if it is not required.
self.stacked_layout.takeAt(pos)
def accept(self): def accept(self):
""" """
@ -137,10 +135,21 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog, RegistryProperties):
if plugin.settings_tab: if plugin.settings_tab:
plugin.settings_tab.post_set_up() plugin.settings_tab.post_set_up()
def tab_changed(self, tab_index): def list_item_changed(self, item_index):
""" """
A different settings tab is selected A different settings tab is selected
:param item_index: The index of the item that was selected
""" """
# Get the item we clicked on
list_item = self.setting_list_widget.item(item_index)
# Loop through the list of tabs in the stacked layout
for tab_index in range(self.stacked_layout.count()):
# Get the widget
tab_widget = self.stacked_layout.itemAt(tab_index).widget()
# Check that the title of the tab (i.e. plugin name) is the same as the data in the list item
if tab_widget.tab_title == list_item.data(QtCore.Qt.UserRole):
# Make the matching tab visible
self.stacked_layout.setCurrentIndex(tab_index) self.stacked_layout.setCurrentIndex(tab_index)
self.stacked_layout.currentWidget().tab_visible() self.stacked_layout.currentWidget().tab_visible()

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman #
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
All the tests
"""

View File

@ -35,7 +35,7 @@ from openlp.core.common import Registry, ThemeLevel
from openlp.core.lib import ServiceItem, ServiceItemType, ItemCapabilities from openlp.core.lib import ServiceItem, ServiceItemType, ItemCapabilities
from openlp.core.ui import ServiceManager from openlp.core.ui import ServiceManager
from tests.interfaces import MagicMock, patch from tests.functional import MagicMock
class TestServiceManager(TestCase): class TestServiceManager(TestCase):

View File

@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman #
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
Package to test the openlp.core.ui.settingsform package.
"""
from unittest import TestCase
from openlp.core.common import Registry
from openlp.core.ui.generaltab import GeneralTab
from openlp.core.ui.settingsform import SettingsForm
from tests.functional import MagicMock, patch
class TestSettingsForm(TestCase):
def setUp(self):
"""
Set up a few things for the tests
"""
Registry.create()
def insert_tab_visible_test(self):
"""
Test that the insert_tab() method works correctly when a visible tab is inserted
"""
# GIVEN: A mocked tab and a Settings Form
settings_form = SettingsForm(None)
general_tab = MagicMock()
general_tab.tab_title = 'mock'
general_tab.tab_title_visible = 'Mock'
general_tab.icon_path = ':/icon/openlp-logo-16x16.png'
# WHEN: We insert the general tab
with patch.object(settings_form.stacked_layout, 'addWidget') as mocked_add_widget, \
patch.object(settings_form.setting_list_widget, 'addItem') as mocked_add_item:
settings_form.insert_tab(general_tab, is_visible=True)
# THEN: Stuff should happen
mocked_add_widget.assert_called_with(general_tab)
self.assertEqual(1, mocked_add_item.call_count, 'addItem should have been called')
def insert_tab_not_visible_test(self):
"""
Test that the insert_tab() method works correctly when a tab that should not be visible is inserted
"""
# GIVEN: A general tab and a Settings Form
settings_form = SettingsForm(None)
general_tab = MagicMock()
general_tab.tab_title = 'mock'
# WHEN: We insert the general tab
with patch.object(settings_form.stacked_layout, 'addWidget') as mocked_add_widget, \
patch.object(settings_form.setting_list_widget, 'addItem') as mocked_add_item:
settings_form.insert_tab(general_tab, is_visible=False)
# THEN: Stuff should happen
mocked_add_widget.assert_called_with(general_tab)
self.assertEqual(0, mocked_add_item.call_count, 'addItem should not have been called')