def _insert_new_edition_panel(self, measure): """Handle inserting a new MeasureEditorDockItem in the content. """ template = 'meas_%d' items = self.dock_area.dock_items() test = re.compile('meas\_([0-9]+)$') measure_items = [i for i in items if test.match(i.name)] if not measure_items: name = template % 0 op = InsertItem(item=name, target='meas_exec') else: indexes = [int(test.match(i.name).group(1)) for i in measure_items] indexes.sort() if len(indexes) <= max(indexes): ind = [i for i, x in enumerate(indexes) if i != x][0] else: ind = len(measure_items) name = template % ind op = InsertTab(item=name, target=template % indexes[0]) MeasureEditorDockItem(self.dock_area, workspace=self, measure=measure, name=name) deferred_call(self.dock_area.update_layout, op)
def _insert_new_edition_panels(self, measurements, update=True, panels=None): """Handle inserting a new MeasurementEditorDockItem in the content. """ if panels is None: template = 'meas_%d' items = self.dock_area.dock_items() test = re.compile('meas\_([0-9]+)$') measurement_items = [i for i in items if test.match(i.name)] ops = [] for measurement in measurements: if not measurement_items: name = template % 0 ops.append(InsertItem(item=name, target='meas_exec')) else: indexes = [ int(test.match(i.name).group(1)) for i in measurement_items ] indexes.sort() if len(indexes) <= max(indexes): ind = [i for i, x in enumerate(indexes) if i != x][0] else: ind = len(measurement_items) name = template % ind ops.append( InsertTab(item=name, target=template % indexes[0])) measurement_items.append( MeasurementEditorDockItem(self.dock_area, workspace=self, measurement=measurement, name=name)) if update: deferred_call(self.dock_area.update_layout, ops) else: for m in measurements: if m not in panels: msg = ('Cannot insert edition panels for measurement %s, ' 'no infos were provided. Panels exists for:\n%s') raise RuntimeError(msg % (m.name + ' (id : %s)' % m.id, ', '.join(m.name for m in panels))) ed_name, t_name = panels[m] MeasurementEditorDockItem(self.dock_area, workspace=self, measurement=m, name=ed_name) if t_name: ToolsEditorDockItem(self.dock_area, measurement=m, name=t_name)
def start_monitors(self, measurement): """Start the monitors attached to a measurement. Called in the main thread. """ workbench = self.plugin.workbench if not self.monitors_window: with enaml.imports(): from .workspace.monitors_window import MonitorsWindow self.monitors_window = MonitorsWindow() else: self.monitors_window.send_to_front() self.monitors_window.measurement = measurement dock_area = self.monitors_window.dock_area anchor = '' for dock_item in dock_area.dock_items(): if dock_item.name not in measurement.monitors: dock_item.destroy() elif not anchor: anchor = dock_item.name # We show the window now because otherwise the layout ops are not # properly executed. if self.plugin.auto_show_monitors: self.monitors_window.show() ops = [] for monitor in measurement.monitors.values(): decl = monitor.declaration dock_item = dock_area.find(decl.id) if dock_item is None: try: dock_item = decl.create_item(workbench, dock_area) except Exception: msg = 'Failed to create widget for monitor %s :\n %s' logger.error(msg, decl.id, format_exc()) continue if dock_item is not None: if dock_item.float_default: ops.append(FloatItem(item=decl.id)) else: ops.append(InsertTab(item=decl.id, target=anchor)) self.engine.observe('progress', monitor.process_news) if dock_item: dock_item.monitor = monitor monitor.start() if ops: dock_area.update_layout(ops)
def test_handling_nested_dock_area(enaml_qtbot, enaml_sleep): """Test that an inner dock area does not look for item in the outer one. """ win = compile_source(NESTED_DOCK_AREA, 'Main')() win.show() wait_for_window_displayed(enaml_qtbot, win) enaml_qtbot.wait(enaml_sleep) dock_item = DockItem(win.inner, name='Inner2', title='Inner2') op = InsertTab(item=dock_item.name, target='Inner1', tab_position='top') win.inner.update_layout(op) enaml_qtbot.wait(enaml_sleep) assert dock_item.parent is win.inner
def start_monitors(self, measure): workbench = self.plugin.workbench if not self.monitors_window: ui_plugin = workbench.get_plugin('enaml.workbench.ui') with enaml.imports(): from .workspace.monitors_window import MonitorsWindow self.monitors_window = MonitorsWindow(ui_plugin.window) self.monitors_window.measure = measure dock_area = self.monitors_window.dock_area anchor = '' for dock_item in dock_area.dock_items(): if dock_item.name not in measure.monitors: dock_item.destroy() elif not anchor: anchor = dock_item.name # We show the window now because otherwise the layout ops are not # properly executed. if self.plugin.auto_show_monitors: self.monitors_window.show() ops = [] for monitor in measure.monitors.values(): decl = monitor.declaration dock_item = dock_area.find(decl.id) if dock_item is None: try: dock_item = decl.create_item(workbench, dock_area) except Exception: logger.error('Failed to create widget for monitor %s', decl.id) logger.debug(format_exc()) continue if dock_item is not None: if dock_item.float_default: ops.append(FloatItem(item=decl.id)) else: ops.append(InsertTab(item=decl.id, target=anchor)) self.engine.observe('progress', monitor.process_news) if dock_item: dock_item.monitor = monitor monitor.start() if ops: dock_area.update_layout(ops)
def test_dock_area_interactions(enaml_qtbot, enaml_sleep): """Test interations with the dock area. """ # Since timers are used the sleep must be greater than the default enaml_sleep = max(300, enaml_sleep) from enaml.qt.QtCore import Qt, QPoint from enaml.qt.QtWidgets import QWidget from enaml.layout.api import FloatItem, InsertTab dir_path = os.path.abspath(os.path.split(os.path.dirname(__file__))[0]) example_path = os.path.join(dir_path, 'examples', 'widgets', 'dock_area.enaml') with open(example_path) as f: source = f.read() win = compile_source(source, 'Main')() win.show() wait_for_window_displayed(enaml_qtbot, win) enaml_qtbot.wait(enaml_sleep) _children = win.children[0].children btn_save, btn_restore, btn_add, cmb_styles, cbx_evts, dock = _children # Enable dock events enaml_qtbot.mouseClick(cbx_evts.proxy.widget, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) with pytest.warns(DockLayoutWarning): # Change styles cmb_styles.proxy.widget.setFocus() enaml_qtbot.keyClick(cmb_styles.proxy.widget, Qt.Key_Up) # Save layout enaml_qtbot.mouseClick(btn_save.proxy.widget, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) # Toggle closable di = dock.find('item_2') di.closable = False enaml_qtbot.wait(enaml_sleep) di.closable = True # Check alert di.alert('info') # Maximize it tb = di.proxy.widget.titleBarWidget() enaml_qtbot.mouseClick(tb._max_button, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) # Minimize it enaml_qtbot.mouseClick(tb._restore_button, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) # Pin it enaml_qtbot.mouseClick(tb._pin_button, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) # TODO: Open and close it using clicks dock_area = dock.proxy.widget for c in dock_area.dockBarContainers(): dock_bar = c[0] dock_area.extendFromDockBar(dock_bar) enaml_qtbot.wait(enaml_sleep) dock_area.retractToDockBar(dock_bar) enaml_qtbot.wait(enaml_sleep) # Unpin enaml_qtbot.mouseClick(tb._pin_button, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) # Note the location of the dock item title title = tb._title_label ref = win.proxy.widget # Maximize and minimize it by double clicking pos = title.mapTo(tb, title.pos()) enaml_qtbot.mouseDClick(tb, Qt.LeftButton, pos=pos) enaml_qtbot.wait(enaml_sleep) enaml_qtbot.mouseDClick(tb, Qt.LeftButton, pos=pos) enaml_qtbot.wait(enaml_sleep) # Float it op = FloatItem(item=di.name) dock.update_layout(op) enaml_qtbot.wait(enaml_sleep) # Link it enaml_qtbot.mouseClick(tb._link_button, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) # Unlink it enaml_qtbot.mouseClick(tb._link_button, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) # Restore it op = InsertTab(item=di.name, target='item_1') dock.update_layout(op) enaml_qtbot.wait(enaml_sleep) # TODO: Drag it around # Add items enaml_qtbot.mouseClick(btn_add.proxy.widget, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) # Close all added items for i in range(10, 15): di = dock.find('item_%i' % i) if di: enaml_qtbot.mouseClick( di.proxy.widget.titleBarWidget()._close_button, Qt.LeftButton) # Restore layout enaml_qtbot.mouseClick(btn_restore.proxy.widget, Qt.LeftButton) enaml_qtbot.wait(enaml_sleep) enaml_qtbot.wait(enaml_sleep)
def _update_area_layout(self, change): """ When a document is opened or closed, add or remove it from the currently active TabLayout. The layout update is deferred so it fires after the items are updated by the Looper. """ if change['type'] == 'create': return #: Get the dock area area = self.get_dock_area() #: Refresh the dock items #area.looper.iterable = self.documents[:] #: Determine what change to apply removed = set() added = set() if change['type'] == 'container': op = change['operation'] if op in ['append', 'insert']: added = set([change['item']]) elif op == 'extend': added = set(change['items']) elif op in ['pop', 'remove']: removed = set([change['item']]) elif change['type'] == 'update': old = set(change['oldvalue']) new = set(change['value']) #: Determine which changed removed = old.difference(new) added = new.difference(old) elif change['type'] == 'manual': old = set([self.active_document]) new = set(self.documents) #: Determine which changed removed = old.difference(new) added = new.difference(old) #: Update operations to apply ops = [] #: Remove any old items for doc in removed: ops.append(RemoveItem(item='editor-item-{}'.format(doc.name))) #: Add any new items for doc in added: targets = [ 'editor-item-{}'.format(d.name) for d in self.documents if d.name != doc.name ] item = EditorItem(area, plugin=self, doc=doc) ops.append( InsertTab(item=item.name, target=targets[0] if targets else '')) #: Now apply all layout update operations print("Updating dock area: {}".format(ops)) area.update_layout(ops) self.save_dock_area(change)
def show_plot(self, plot_type, **traits): """ Show a plot in a new tab. """ item = PLOT_TYPES[plot_type](**traits) op = InsertTab(target = 'input_table') self.add_dock_item(item, op)
def _update_area_layout(self, change): """ When a document is opened or closed, add or remove it from the currently active TabLayout. The layout update is deferred so it fires after the items are updated by the Looper. """ if change['type'] == 'create': return #: Get the dock area area = self.get_dock_area() #: Refresh the dock items #area.looper.iterable = self.documents[:] #: Determine what change to apply removed = set() added = set() if change['type'] == 'container': op = change['operation'] if op in ['append', 'insert']: added = set([change['item']]) elif op == 'extend': added = set(change['items']) elif op in ['pop', 'remove']: removed = set([change['item']]) elif change['type'] == 'update': old = set(change['oldvalue']) new = set(change['value']) #: Determine which changed removed = old.difference(new) added = new.difference(old) elif change['type'] == 'load': old = set([Document()]) new = set(self.documents) #: Determine which changed removed = old.difference(new) added = new.difference(old) #: Update operations to apply ops = [] removed_targets = [] #: Remove any old items for doc in removed: for item in self.get_editor_items(): if item.doc == doc: removed_targets.append(item.name) ops.append(RemoveItem(item=item.name)) # Remove ops area.update_layout(ops) # Add each one at a time targets = [ item.name for item in area.dock_items() if (item.name.startswith("editor-item") and item.name not in removed_targets) ] # Sort documents so active is last so it's on top when we restore # from a previous state for doc in sorted(added, key=lambda d: int(d == self.active_document)): item = create_editor_item(area, plugin=self, doc=doc) if targets: op = InsertTab(item=item.name, target=targets[-1]) else: op = InsertItem(item=item.name) targets.append(item.name) area.update_layout(op) # Now save it self.save_dock_area(change)