def set_selected_multiple(editor, rows): """ Clears old selection and selects specified rows in an editor with multi_select=True. """ if is_wx(): clear_selection(editor) for row in rows: editor.control.Select(row) elif is_qt(): from pyface.qt.QtGui import QItemSelectionModel clear_selection(editor) smodel = editor.control.selectionModel() for row in rows: mi = editor.model.index(row, 0) # Add `Rows` flag to select the whole row smodel.select( mi, QItemSelectionModel.Select | QItemSelectionModel.Rows) else: raise unittest.SkipTest("Test not implemented for this toolkit")
def set_combobox_text(combobox, text): """ Set the text given a combobox control """ if is_wx(): import wx if isinstance(combobox, wx.Choice): event_type = wx.EVT_CHOICE.typeId event = wx.CommandEvent(event_type, combobox.GetId()) event.SetString(text) wx.PostEvent(combobox, event) else: combobox.SetValue(text) event_type = wx.EVT_COMBOBOX.typeId event = wx.CommandEvent(event_type, combobox.GetId()) event.SetString(text) wx.PostEvent(combobox, event) elif is_qt(): combobox.setEditText(text) else: raise unittest.SkipTest("Test not implemented for this toolkit")
def test_list_str_editor_multi_selection_changed(self): view = get_view(multi_select=True) with reraise_exceptions(), self.setup_gui( ListStrModel(), view ) as editor: self.assertEqual(get_selected_indices(editor), []) editor.multi_selected_indices = [0, 1] process_cascade_events() self.assertEqual(get_selected_indices(editor), [0, 1]) self.assertEqual(editor.multi_selected, ["one", "two"]) editor.multi_selected = ["three", "one"] process_cascade_events() self.assertEqual(sorted(get_selected_indices(editor)), [0, 2]) self.assertEqual(sorted(editor.multi_selected_indices), [0, 2]) editor.multi_selected = ["three", "four"] process_cascade_events() if is_qt(): # Invalid values assigned to multi_selected are ignored self.assertEqual(get_selected_indices(editor), [2]) self.assertEqual(editor.multi_selected_indices, [2]) elif is_wx(): # Selection indices are not updated at all self.assertEqual(get_selected_indices(editor), [0, 2]) self.assertEqual(editor.multi_selected_indices, [0, 2]) # Setting selected indices to an empty list clears selection editor.multi_selected_indices = [] process_cascade_events() self.assertEqual(get_selected_indices(editor), []) self.assertEqual(editor.multi_selected, [])
def get_selected_indices(editor): """ Returns a list of the indices of all currently selected list items. """ if is_wx(): import wx # "item" in this context means "index of the item" item = -1 selected = [] while True: item = editor.control.GetNextItem(item, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) if item == -1: break selected.append(item) return selected elif is_qt(): indices = editor.list_view.selectionModel().selectedRows() return [i.row() for i in indices] else: raise unittest.SkipTest("Test not implemented for this toolkit")
def get_selected_rows(editor): """ Returns a list of all currently selected rows. """ if is_wx(): import wx # "item" in this context means "row number" item = -1 selected = [] while True: item = editor.control.GetNextItem(item, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) if item == -1: break selected.append(item) return selected elif is_qt(): rows = editor.control.selectionModel().selectedRows() return [r.row() for r in rows] else: raise unittest.SkipTest("Test not implemented for this toolkit")
def test_simple_set_editor_deleted_valid_values(self): editor_factory = SetEditor(values=["one", "two", "three", "four"]) view = View(UItem("value", editor=editor_factory, style="simple",)) list_edit = ListModel() with reraise_exceptions(), \ self.setup_gui(list_edit, view) as editor: self.assertEqual(get_list_items(editor._unused), ["four", "three"]) self.assertEqual(get_list_items(editor._used), ["one", "two"]) editor_factory.values = ["two", "three", "four"] process_cascade_events() self.assertEqual(get_list_items(editor._unused), ["four", "three"]) # FIXME issue enthought/traitsui#840 if is_wx(): with self.assertRaises(AssertionError): self.assertEqual(get_list_items(editor._used), ["two"]) self.assertEqual(get_list_items(editor._used), ["one", "two"]) else: self.assertEqual(get_list_items(editor._used), ["two"]) self.assertEqual(list_edit.value, ["two"])
def test_range_text_editor_set_with_text_valid(self): model = RangeModel() view = View( Item( "value", editor=RangeEditor(low=1, high=12, mode="text") ) ) tester = UITester() with tester.create_ui(model, dict(view=view)) as ui: # sanity check self.assertEqual(model.value, 1) number_field_text = tester.find_by_name(ui, "value") if is_windows and is_wx(): # For RangeTextEditor on wx and windows, the textbox # automatically gets focus and the full content is selected. # Insertion point is moved to keep the test consistent number_field_text.perform(KeyClick("End")) number_field_text.perform(KeyClick("0")) number_field_text.perform(KeyClick("Enter")) displayed = number_field_text.inspect(DisplayedText()) self.assertEqual(model.value, 10) self.assertEqual(displayed, str(model.value))
class TestTabularEditor(BaseTestMixin, UnittestTools, unittest.TestCase): def setUp(self): BaseTestMixin.setUp(self) def tearDown(self): BaseTestMixin.tearDown(self) @unittest.skipIf(is_wx(), "Issue enthought/traitsui#752") def test_tabular_editor_single_selection(self): with reraise_exceptions(), \ self.report_and_editor(get_view()) as (report, editor): process_cascade_events() people = report.people self.assertEqual(report.selected_row, -1) self.assertIsNone(report.selected) set_selected_single(editor, 1) process_cascade_events() self.assertEqual(report.selected_row, 1) self.assertEqual(report.selected, people[1]) set_selected_single(editor, 2) process_cascade_events() self.assertEqual(report.selected_row, 2) self.assertEqual(report.selected, people[2]) # Can't clear selection via UI when multi_select=False @unittest.skipIf(is_wx(), "Issue enthought/traitsui#752") def test_tabular_editor_multi_selection(self): view = get_view(multi_select=True) with reraise_exceptions(), \ self.report_and_editor(view) as (report, editor): process_cascade_events() people = report.people self.assertEqual(report.selected_rows, []) self.assertEqual(report.multi_selected, []) set_selected_multiple(editor, [0, 1]) process_cascade_events() self.assertEqual(report.selected_rows, [0, 1]) self.assertEqual(report.multi_selected, people[:2]) set_selected_multiple(editor, [2]) process_cascade_events() self.assertEqual(report.selected_rows, [2]) self.assertEqual(report.multi_selected, [people[2]]) clear_selection(editor) process_cascade_events() self.assertEqual(report.selected_rows, []) self.assertEqual(report.multi_selected, []) @unittest.skipIf(is_wx(), "Issue enthought/traitsui#752") def test_tabular_editor_single_selection_changed(self): with reraise_exceptions(), \ self.report_and_editor(get_view()) as (report, editor): process_cascade_events() people = report.people self.assertEqual(get_selected_rows(editor), []) report.selected_row = 1 process_cascade_events() self.assertEqual(get_selected_rows(editor), [1]) self.assertEqual(report.selected, people[1]) report.selected = people[2] process_cascade_events() self.assertEqual(get_selected_rows(editor), [2]) self.assertEqual(report.selected_row, 2) # Selected set to invalid value doesn't change anything report.selected = Person(name="invalid", age=-1) process_cascade_events() self.assertEqual(get_selected_rows(editor), [2]) self.assertEqual(report.selected_row, 2) # -1 clears selection report.selected_row = -1 process_cascade_events() self.assertEqual(get_selected_rows(editor), []) self.assertEqual(report.selected, None) @unittest.skipIf(is_wx(), "Issue enthought/traitsui#752") def test_tabular_editor_multi_selection_changed(self): view = get_view(multi_select=True) with reraise_exceptions(), \ self.report_and_editor(view) as (report, editor): process_cascade_events() people = report.people self.assertEqual(get_selected_rows(editor), []) report.selected_rows = [0, 1] process_cascade_events() self.assertEqual(get_selected_rows(editor), [0, 1]) self.assertEqual(report.multi_selected, people[:2]) report.multi_selected = [people[2], people[0]] process_cascade_events() self.assertEqual(sorted(get_selected_rows(editor)), [0, 2]) self.assertEqual(sorted(report.selected_rows), [0, 2]) # If there's a single invalid value, nothing is updated invalid_person = Person(name="invalid", age=-1) report.multi_selected = [people[2], invalid_person] process_cascade_events() self.assertEqual(sorted(get_selected_rows(editor)), [0, 2]) self.assertEqual(sorted(report.selected_rows), [0, 2]) # Empty list clears selection report.selected_rows = [] process_cascade_events() self.assertEqual(get_selected_rows(editor), []) self.assertEqual(report.multi_selected, []) @unittest.skipIf(is_wx(), "Issue enthought/traitsui#752") def test_tabular_editor_multi_selection_items_changed(self): view = get_view(multi_select=True) with reraise_exceptions(), \ self.report_and_editor(view) as (report, editor): process_cascade_events() people = report.people self.assertEqual(get_selected_rows(editor), []) report.selected_rows.extend([0, 1]) process_cascade_events() self.assertEqual(get_selected_rows(editor), [0, 1]) self.assertEqual(report.multi_selected, people[:2]) report.selected_rows[1] = 2 process_cascade_events() self.assertEqual(get_selected_rows(editor), [0, 2]) self.assertEqual(report.multi_selected, people[0:3:2]) report.multi_selected[0] = people[1] process_cascade_events() self.assertEqual(sorted(get_selected_rows(editor)), [1, 2]) self.assertEqual(sorted(report.selected_rows), [1, 2]) # If there's a single invalid value, nothing is updated report.multi_selected[0] = Person(name="invalid", age=-1) process_cascade_events() self.assertEqual(sorted(get_selected_rows(editor)), [1, 2]) self.assertEqual(sorted(report.selected_rows), [1, 2]) def test_selected_reacts_to_model_changes(self): with self.report_and_editor(get_view()) as (report, editor): people = report.people self.assertIsNone(report.selected) self.assertEqual(report.selected_row, -1) report.selected = people[1] self.assertEqual(report.selected, people[1]) self.assertEqual(report.selected_row, 1) report.selected = None self.assertIsNone(report.selected) self.assertEqual(report.selected_row, -1) report.selected_row = 0 self.assertEqual(report.selected, people[0]) self.assertEqual(report.selected_row, 0) report.selected_row = -1 self.assertIsNone(report.selected) self.assertEqual(report.selected_row, -1) def test_event_synchronization(self): with self.report_and_editor(get_view()) as (report, editor): with self.assertTraitChanges(editor, "refresh", count=1): report.refresh = True # Should happen every time. with self.assertTraitChanges(editor, "refresh", count=1): report.refresh = True with self.assertTraitChanges(editor, "update", count=1): report.update = True with self.assertTraitChanges(editor, "update", count=1): report.update = True def test_adapter_columns_changes(self): # Regression test for enthought/traitsui#894 with reraise_exceptions(), \ self.report_and_editor(get_view()) as (report, editor): # Reproduce the scenario when the column count is reduced. editor.adapter.columns = [ ("Name", "name"), ("Age", "age"), ] # Recalculating column widths take into account the user defined # widths, cached in the view. The cache should be invalidated # when the columns is updated such that recalculation does not # fail. editor.adapter.columns = [("Name", "name")] process_cascade_events() def test_view_column_resized_attribute_error_workaround(self): # This tests the workaround which checks if `factory` is None before # using it while resizing the columns. # The resize event is processed after UI.dispose is called. # Maybe related to enthought/traits#431 with reraise_exceptions(), \ self.report_and_editor(get_view()) as (_, editor): editor.adapter.columns = [("Name", "name")] @contextlib.contextmanager def report_and_editor(self, view): """ Context manager to temporarily create and clean up a Report model object and the corresponding TabularEditor. """ report = Report( people=[ Person(name="Theresa", age=60), Person(name="Arlene", age=46), Person(name="Karen", age=40), ] ) with create_ui(report, dict(view=view)) as ui: editor, = ui.get_editors("people") yield report, editor
self.max_n_events = max_n_events self.n_events = 0 def event(self, event): if event.type() != QtCore.QEvent.User: return super().event(event) self.n_events += 1 if self.n_events < self.max_n_events: new_event = QtCore.QEvent(QtCore.QEvent.User) QtCore.QCoreApplication.postEvent(self, new_event) return True if is_wx(): # Create a wx.EvtHandler that will emit a new event to itself as long as # it has not received enough. import wx import wx.lib.newevent NewEvent, EVT_SOME_NEW_EVENT = wx.lib.newevent.NewEvent() class DummyWxHandler(wx.EvtHandler): def __init__(self, max_n_events): super().__init__() self.max_n_events = max_n_events self.n_events = 0
"This example depends on PyTables which may be built to require CPUs with " "a specific AVX version that is not supported on a paricular OSX host.", ) SEARCHER.skip_file_if( os.path.join(DEMO, "Advanced", "Table_editor_with_progress_column.py"), is_wx, "ProgressRenderer is not implemented in wx.", ) SEARCHER.skip_file_if( os.path.join(DEMO, "Advanced", "Scrubber_editor_demo.py"), is_qt, "ScrubberEditor is not implemented in qt.", ) SEARCHER.skip_file_if( os.path.join(DEMO, "Extras", "animated_GIF.py"), lambda: not is_wx(), "Only support wx", ) SEARCHER.skip_file_if( os.path.join(DEMO, "Extras", "Tree_editor_with_TreeNodeRenderer.py"), lambda: not is_qt(), "Only support Qt", ) SEARCHER.skip_file_if( os.path.join(DEMO, "Extras", "windows", "flash.py"), lambda: not is_wx(), "Only support wx", ) SEARCHER.skip_file_if( os.path.join(DEMO, "Extras", "windows", "internet_explorer.py"), lambda: not is_wx(),
from pyface.qt import QtCore from pyface.qt.QtTest import QTest view = editor.list_view rect = view.rect() QTest.mouseClick( view.viewport(), QtCore.Qt.MouseButton.RightButton, QtCore.Qt.KeyboardModifier.NoModifier, rect.center(), ) else: raise unittest.SkipTest("Test not implemented for this toolkit") @unittest.skipIf(is_wx(), "Issue enthought/traitsui#752") @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) class TestListStrEditor(BaseTestMixin, unittest.TestCase): def setUp(self): BaseTestMixin.setUp(self) def tearDown(self): BaseTestMixin.tearDown(self) @contextlib.contextmanager def setup_gui(self, model, view): with create_ui(model, dict(view=view)) as ui: process_cascade_events() editor = ui.get_editors("value")[0] yield editor