From 94fca706ff35ef0ef280722c55ebe5e5e05b3967 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Thu, 10 Nov 2016 07:09:04 +0000 Subject: [PATCH] Move no results functionality to the ListWidgetWithDnD --- openlp/core/lib/mediamanageritem.py | 30 -------------- openlp/core/ui/lib/listwidgetwithdnd.py | 41 +++++++++++++++++-- openlp/plugins/bibles/lib/mediaitem.py | 22 ++-------- openlp/plugins/custom/lib/mediaitem.py | 2 - openlp/plugins/songs/lib/mediaitem.py | 1 - .../openlp_plugins/bibles/test_mediaitem.py | 4 -- 6 files changed, 42 insertions(+), 58 deletions(-) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 2edea93cf..378020812 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -397,8 +397,6 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): # Decide if we have to show the context menu or not. if item is None: return - if not item.flags() & QtCore.Qt.ItemIsSelectable: - return self.menu.exec(self.list_view.mapToGlobal(point)) def get_file_list(self): @@ -638,34 +636,6 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): """ return item - def check_search_result(self): - """ - Checks if the list_view is empty and adds a "No Search Results" item. - """ - if self.list_view.count(): - return - message = translate('OpenLP.MediaManagerItem', 'No Search Results') - item = QtWidgets.QListWidgetItem(message) - item.setFlags(QtCore.Qt.NoItemFlags) - font = QtGui.QFont() - font.setItalic(True) - item.setFont(font) - self.list_view.addItem(item) - - def check_search_result_search_while_typing_short(self): - """ - This is used in Bible "Search while typing" if the search is shorter than the min required len. - """ - if self.list_view.count(): - return - message = translate('OpenLP.MediaManagerItem', 'Search is too short to be used in: "Search while typing"') - item = QtWidgets.QListWidgetItem(message) - item.setFlags(QtCore.Qt.NoItemFlags) - font = QtGui.QFont() - font.setItalic(True) - item.setFont(font) - self.list_view.addItem(item) - def _get_id_of_item_to_generate(self, item, remote_item): """ Utility method to check items being submitted for slide generation. diff --git a/openlp/core/ui/lib/listwidgetwithdnd.py b/openlp/core/ui/lib/listwidgetwithdnd.py index 43ec741d0..23bdbcd2d 100644 --- a/openlp/core/ui/lib/listwidgetwithdnd.py +++ b/openlp/core/ui/lib/listwidgetwithdnd.py @@ -26,7 +26,10 @@ import os from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common import Registry +from openlp.core.common import Registry, translate + +NO_RESULTS = translate('OpenLP.ListWidgetWithDnD', 'No Search Results') +SHORT_RESULTS = translate('OpenLP.ListWidgetWithDnD', 'Please type more text to use \'Search As You Type\'') class ListWidgetWithDnD(QtWidgets.QListWidget): @@ -37,8 +40,9 @@ class ListWidgetWithDnD(QtWidgets.QListWidget): """ Initialise the list widget """ - super(ListWidgetWithDnD, self).__init__(parent) + super().__init__(parent) self.mime_data_text = name + self.no_results_text = NO_RESULTS def activateDnD(self): """ @@ -48,6 +52,19 @@ class ListWidgetWithDnD(QtWidgets.QListWidget): self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().load_file) + def clear(self, search_while_typing=False): + """ + Re-implement clear, so that we can customise feedback when using 'Search as you type' + + :param search_while_typing: True if we want to display the customised message + :return: None + """ + if search_while_typing: + self.no_results_text = SHORT_RESULTS + else: + self.no_results_text = NO_RESULTS + super().clear() + def mouseMoveEvent(self, event): """ Drag and drop event does not care what data is selected as the recipient will use events to request the data @@ -102,6 +119,24 @@ class ListWidgetWithDnD(QtWidgets.QListWidget): listing = os.listdir(local_file) for file in listing: files.append(os.path.join(local_file, file)) - Registry().execute('%s_dnd' % self.mime_data_text, {'files': files, 'target': self.itemAt(event.pos())}) + Registry().execute('{mime_data}_dnd'.format(mime_data=self.mime_data_text), + {'files': files, 'target': self.itemAt(event.pos())}) else: event.ignore() + + def paintEvent(self, event): + """ + Re-implement paintEvent so that we can add 'No Results' text when the listWidget is empty. + + :param event: A QPaintEvent + :return: None + """ + super().paintEvent(event) + if not self.count(): + viewport = self.viewport() + painter = QtGui.QPainter(viewport) + font = QtGui.QFont() + font.setItalic(True) + painter.setFont(font) + painter.drawText(QtCore.QRect(0, 0, viewport.width(), viewport.height()), + (QtCore.Qt.AlignHCenter | QtCore.Qt.TextWordWrap), self.no_results_text) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index fc92b8f7a..f9329d503 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -75,21 +75,16 @@ class BibleMediaItem(MediaManagerItem): self.has_search = True self.search_results = {} self.second_search_results = {} - self.check_search_result() Registry().register_function('bibles_load_list', self.reload_bibles) def __check_second_bible(self, bible, second_bible): """ Check if the first item is a second bible item or not. """ - bitem = self.list_view.item(0) - if not bitem.flags() & QtCore.Qt.ItemIsSelectable: - # The item is the "No Search Results" item. - self.list_view.clear() + if not self.list_view.count(): self.display_results(bible, second_bible) return - else: - item_second_bible = self._decode_qt_object(bitem, 'second_bible') + item_second_bible = self._decode_qt_object(self.list_view.item(0), 'second_bible') if item_second_bible and second_bible or not item_second_bible and not second_bible: self.display_results(bible, second_bible) elif critical_error_message_box( @@ -551,14 +546,12 @@ class BibleMediaItem(MediaManagerItem): def on_clear_button_clicked(self): # Clear the list, then set the "No search Results" message, then clear the text field and give it focus. self.list_view.clear() - self.check_search_result() self.quick_search_edit.clear() self.quick_search_edit.setFocus() def on_advanced_clear_button_clicked(self): # The same as the on_clear_button_clicked, but gives focus to Book name field in "Select" (advanced). self.list_view.clear() - self.check_search_result() self.advanced_book_combo_box.setFocus() def on_lock_button_toggled(self, checked): @@ -692,7 +685,6 @@ class BibleMediaItem(MediaManagerItem): elif self.search_results: self.display_results(bible, second_bible) self.advancedSearchButton.setEnabled(True) - self.check_search_result() self.application.set_normal_cursor() def on_quick_reference_search(self): @@ -886,7 +878,6 @@ class BibleMediaItem(MediaManagerItem): elif self.search_results: self.display_results(bible, second_bible) self.quickSearchButton.setEnabled(True) - self.check_search_result() self.application.set_normal_cursor() def on_quick_search_while_typing(self): @@ -917,7 +908,6 @@ class BibleMediaItem(MediaManagerItem): self.__check_second_bible(bible, second_bible) elif self.search_results: self.display_results(bible, second_bible) - self.check_search_result() self.application.set_normal_cursor() def on_search_text_edit_changed(self): @@ -956,17 +946,13 @@ class BibleMediaItem(MediaManagerItem): if len(text) == 0: if not self.quickLockButton.isChecked(): self.list_view.clear() - self.check_search_result() else: if limit == 3 and (len(text) < limit or len(count_space_digit_reference) == 0): if not self.quickLockButton.isChecked(): self.list_view.clear() - self.check_search_result() - elif (limit == 8 and (len(text) < limit or len(count_spaces_two_chars_text) == 0 or - len(count_two_chars_text) < 2)): + elif (limit == 8 and len(text) < limit ): if not self.quickLockButton.isChecked(): - self.list_view.clear() - self.check_search_result_search_while_typing_short() + self.list_view.clear(search_while_typing=True) else: """ Start search if no chars are entered or deleted for 0.2 s diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 2b999da19..e3b730294 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -131,7 +131,6 @@ class CustomMediaItem(MediaManagerItem): # Called to redisplay the custom list screen edith from a search # or from the exit of the Custom edit dialog. If remote editing is # active trigger it and clean up so it will not update again. - self.check_search_result() def on_new_click(self): """ @@ -268,7 +267,6 @@ class CustomMediaItem(MediaManagerItem): CustomSlide.theme_name.like(search_keywords), order_by_ref=CustomSlide.title) self.load_list(search_results) - self.check_search_result() def on_search_text_edit_changed(self, text): """ diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index b89858019..1d060f484 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -232,7 +232,6 @@ class SongMediaItem(MediaManagerItem): search_results = self.plugin.manager.get_all_objects( Song, and_(Song.ccli_number.like(search_string), Song.ccli_number != '')) self.display_results_cclinumber(search_results) - self.check_search_result() def search_entire(self, search_keywords): search_string = '%{text}%'.format(text=clean_string(search_keywords)) diff --git a/tests/functional/openlp_plugins/bibles/test_mediaitem.py b/tests/functional/openlp_plugins/bibles/test_mediaitem.py index 28a755fd6..d4a6eee39 100644 --- a/tests/functional/openlp_plugins/bibles/test_mediaitem.py +++ b/tests/functional/openlp_plugins/bibles/test_mediaitem.py @@ -155,7 +155,6 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.list_view = MagicMock() self.media_item.search_results = MagicMock() self.media_item.display_results = MagicMock() - self.media_item.check_search_result = MagicMock() self.app.set_normal_cursor = MagicMock() # WHEN: on_quick_search_button is called @@ -169,7 +168,6 @@ class TestMediaItem(TestCase, TestMixin): self.assertEqual(1, self.media_item.quickLockButton.isChecked.call_count, 'Lock Should had been called once') self.assertEqual(1, self.media_item.display_results.call_count, 'Display results Should had been called once') self.assertEqual(2, self.media_item.quickSearchButton.setEnabled.call_count, 'Disable and Enable the button') - self.assertEqual(1, self.media_item.check_search_result.call_count, 'Check results Should had been called once') self.assertEqual(1, self.app.set_normal_cursor.call_count, 'Normal cursor should had been called once') def test_on_clear_button_clicked(self): @@ -178,7 +176,6 @@ class TestMediaItem(TestCase, TestMixin): """ # GIVEN: Mocked list_view, check_search_results & quick_search_edit. self.media_item.list_view = MagicMock() - self.media_item.check_search_result = MagicMock() self.media_item.quick_search_edit = MagicMock() # WHEN: on_clear_button_clicked is called @@ -186,7 +183,6 @@ class TestMediaItem(TestCase, TestMixin): # THEN: Search result should be reset and search field should receive focus. self.media_item.list_view.clear.assert_called_once_with(), - self.media_item.check_search_result.assert_called_once_with(), self.media_item.quick_search_edit.clear.assert_called_once_with(), self.media_item.quick_search_edit.setFocus.assert_called_once_with()