def __init__(self, *args): """ Initialise the instance. """ QtGui.QSplitter.__init__(self, *args) self.clear() QtCore.QObject.connect( QtGui.QApplication.instance(), QtCore.SIGNAL('focusChanged(QWidget *,QWidget *)'), self._focus_changed)
def sizeHint(self): # Suggest a size that is 80 characters wide and 40 lines tall. style = self.style() opt = QtGui.QStyleOptionHeader() font_metrics = QtGui.QFontMetrics(self.document().defaultFont()) width = font_metrics.width(' ') * 80 width += self.line_number_widget.sizeHint().width() width += self.status_widget.sizeHint().width() width += style.pixelMetric(QtGui.QStyle.PM_ScrollBarExtent, opt, self) height = font_metrics.height() * 40 return QtCore.QSize(width, height)
def __init__(self, parent, pyface_wizard): """ Initialise the object. """ QtGui.QWizard.__init__(self, parent) self._pyface_wizard = pyface_wizard self._controller = pyface_wizard.controller self._ids = {} QtCore.QObject.connect(self, QtCore.SIGNAL('currentIdChanged(int)'), self._update_controller)
def removeRows(self, row, count, parent=QtCore.QModelIndex()): """Reimplemented to allow row deletion, as well as reordering via drag and drop.""" editor = self._editor items = editor.items() self.beginRemoveRows(parent, row, row + count - 1) for i in xrange(count): editor.callx(items.pop, row + i) self.endRemoveRows() return True
def update_editor(self): """ Updates the editor when the object trait changes externally to the editor. """ self.mapper = QtCore.QSignalMapper(self.control) # Disconnect the editor from any control about to be destroyed: self._dispose_items() layout = self.control.layout() # Create all of the list item trait editors: trait_handler = self._trait_handler resizable = ((trait_handler.minlen != trait_handler.maxlen) and self.mutable) item_trait = trait_handler.item_trait is_fake = (resizable and (len(self.value) == 0)) if is_fake: self.empty_list() else: # Asking the mapper to send the sender to the callback method self.mapper.mapped[QtCore.QObject].connect(self.popup_menu) editor = self._editor for index, value in enumerate(self.value): row, column = divmod(index, self.factory.columns) # Account for the fact that we have <columns> number of # pairs column = column * 2 if resizable: # Connecting the new button to the mapper control = IconButton('list_editor.png', self.mapper.map) # Setting the mapping and asking it to send the index of the # sender to the callback method self.mapper.setMapping(control, control) layout.addWidget(control, row, column) proxy = ListItemProxy(self.object, self.name, index, item_trait, value) if resizable: control.proxy = proxy peditor = editor(self.ui, proxy, 'value', self.description, self.control).set(object_name='') peditor.prepare(self.control) pcontrol = peditor.control pcontrol.proxy = proxy if isinstance(pcontrol, QtGui.QWidget): layout.addWidget(pcontrol, row, column + 1) else: layout.addLayout(pcontrol, row, column + 1)
def open_and_run(self, when_opened, *args, **kwargs): """ Execute the function to open the dialog and run ``when_opened``. Parameters ---------- when_opened : callable A callable to be called when the dialog has been created and opened. The callable with be called with the tester instance as argument. *args, **kwargs : Additional arguments to be passed to the `function` attribute of the tester. Raises ------ AssertionError if an assertion error was captured during the deferred calls that open and close the dialog. RuntimeError if a result value has not been assigned within 15 seconds after calling `self.function` Any other exception that was captured during the deferred calls that open and close the dialog. .. note:: This method is synchronous """ condition_timer = QtCore.QTimer() def handler(): """ Run the when_opened as soon as the dialog has opened. """ if self.dialog_opened(): self._gui.invoke_later(when_opened, self) self.dialog_was_opened = True else: condition_timer.start() # Setup and start the timer to fire the handler every 100 msec. condition_timer.setInterval(100) condition_timer.setSingleShot(True) condition_timer.timeout.connect(handler) condition_timer.start() self._assigned = False try: # open the dialog on a deferred call. self._gui.invoke_later(self.open, *args, **kwargs) # wait in the event loop until timeout or a return value assigned. self._helper.event_loop_until_condition( condition=self.value_assigned, timeout=15) finally: condition_timer.stop() condition_timer.timeout.disconnect(handler) self._helper.event_loop() self.assert_no_errors_collected()
def init(self, parent): super(_TabListEditor, self).init(parent) self.control = QtGui.QTabBar() self.control.setDocumentMode(True) for name in self.names: self.control.addTab(str(name)) QtCore.QObject.connect(self.control, QtCore.SIGNAL('currentChanged(int)'), self.update_object)
def create_control(self, parent): """Creates the initial editor control.""" self.control = QtGui.QWidget() layout = QtGui.QGridLayout(self.control) layout.setContentsMargins(0, 0, 0, 0) self._mapper = QtCore.QSignalMapper() if is_pyside and QtCore.__version_info__ >= (5, 15): self._mapper.mappedString.connect(self.update_object) else: self._mapper.mapped[str].connect(self.update_object)
def _qt4_create_view_dock_widget(self, view, size=(-1, -1)): """ Create a dock widget that wraps a view. """ # See if it has already been created. try: dw = view._qt4_dock except AttributeError: dw = QtGui.QDockWidget(view.name, self.window.control) dw.setWidget(_ViewContainer(size, self.window.control)) dw.setObjectName(view.id) dw.connect(dw.toggleViewAction(), QtCore.SIGNAL('toggled(bool)'), self._qt4_handle_dock_visibility) dw.connect(dw, QtCore.SIGNAL('visibilityChanged(bool)'), self._qt4_handle_dock_visibility) # Save the dock window. view._qt4_dock = dw def on_name_changed(): view._qt4_dock.setWindowTitle(view.name) view.on_trait_change(on_name_changed, 'name') # Make sure the view control exists. if view.control is None: # Make sure that the view knows which window it is in. view.window = self.window try: view.control = view.create_control(self.window.control) except: # Tidy up if the view couldn't be created. delattr(view, '_qt4_dock') self.window.control.removeDockWidget(dw) dw.deleteLater() del dw raise dw.widget().setCentralWidget(view.control) return dw
def paintEvent(self, e): """ Copy the image from the buffer to the qt.drawable. In Qt, all drawing should be done inside of here when a widget is shown onscreen. """ if self.buffer is None: return logger.debug('FigureCanvasQtAggLocal.paintEvent: '.format( self, self.get_width_height())) if self.blit_buffer is None: # convert the Agg rendered image -> qImage qImage = QtGui.QImage(self.buffer, self.buffer_width, self.buffer_height, QtGui.QImage.Format_RGBA8888) # get the rectangle for the image rect = qImage.rect() p = QtGui.QPainter(self) # reset the image area of the canvas to be the back-ground color p.eraseRect(rect) # draw the rendered image on to the canvas p.drawPixmap(QtCore.QPoint(0, 0), QtGui.QPixmap.fromImage(qImage)) p.end() else: qImage = QtGui.QImage(self.blit_buffer, self.blit_width, self.blit_height, QtGui.QImage.Format_ARGB32) pixmap = QtGui.QPixmap.fromImage(qImage) p = QtGui.QPainter(self) p.drawPixmap( QtCore.QPoint(self.blit_left, self.buffer_height - self.blit_top), pixmap) p.end() self.blit_buffer = None
def _create_contents(self, parent): label = QtGui.QLabel() if parent.parent() is not None: title = parent.parent().windowTitle() else: title = "" # Set the title. self.title = "About %s" % title # Load the image to be displayed in the about box. image = self.image.create_image() path = self.image.absolute_path # The additional strings. additions = '<br />'.join(self.additions) # Get the version numbers. py_version = sys.version[0:sys.version.find("(")] qt_version = QtCore.__version__ # Set the page contents. label.setText(_DIALOG_TEXT % (path, additions, py_version, qt_version)) # Create the button. buttons = QtGui.QDialogButtonBox() if self.ok_label: buttons.addButton(self.ok_label, QtGui.QDialogButtonBox.AcceptRole) else: buttons.addButton(QtGui.QDialogButtonBox.Ok) buttons.connect(buttons, QtCore.SIGNAL('accepted()'), parent, QtCore.SLOT('accept()')) lay = QtGui.QVBoxLayout() lay.addWidget(label) lay.addWidget(buttons) parent.setLayout(lay)
def insertRows(self, row, count, parent=QtCore.QModelIndex()): """Reimplemented to allow creation of new items.""" editor = self._editor adapter = editor.adapter self.beginInsertRows(parent, row, row + count - 1) for i in range(count): value = adapter.get_default_value(editor.object, editor.name) editor.callx(adapter.insert, editor.object, editor.name, row, value) self.endInsertRows() return True
def arc(self, x, y, r, start_angle, end_angle, clockwise=False): sweep_angle = ( end_angle - start_angle if not clockwise else start_angle - end_angle ) self.path.moveTo(x, y) self.path.arcTo( QtCore.QRectF(x - r, y - r, r * 2, r * 2), np.rad2deg(start_angle), np.rad2deg(sweep_angle), )
def close(self): # Don't fire signals for editors that have destroyed their controls. QtCore.QObject.disconnect(self._qt4_editor_area, QtCore.SIGNAL('hasFocus'), self._qt4_editor_focus) self._qt4_editor_area.clear() # Delete all dock widgets. for v in self.window.views: if self.contains_view(v): self._qt4_delete_view_dock_widget(v)
def _window_paint(self, event): if self.control is None: return # self._gc is an image context w = self._gc.width() h = self._gc.height() data = self._gc.pixel_map.convert_to_argb32string() image = QtGui.QImage(data, w, h, QtGui.QImage.Format_ARGB32) rect = QtCore.QRect(0, 0, w, h) painter = QtGui.QPainter(self.control) painter.drawImage(rect, image)
def update_editor(self): """ Updates the editor when the object trait changes externally to the editor. """ value = self.value if isinstance(value, SVGDocument): string_io = StringIO() ElementTree(value.tree).write(string_io) value = string_io.getvalue() self.control.load(QtCore.QByteArray(value))
def create_dialog(self, parent, style): """Create the dialog control.""" self.control = control = _StickyDialog(self.ui, parent) view = self.ui.view control.setModal(style == BaseDialog.MODAL) control.setWindowTitle(view.title or DefaultTitle) QtCore.QObject.connect(control, QtCore.SIGNAL('finished(int)'), self._on_finished)
def test_vertical_mouse_wheel_without_pixel_delta(self): from pyface.qt import QtCore, QtGui is_qt4 = (QtCore.__version_info__[0] <= 4) if is_qt4: self.skipTest("Not directly applicable in Qt4") # create and mock a mouse wheel event qt_event = QtGui.QWheelEvent( QtCore.QPointF(0, 0), self.window.control.mapToGlobal(QtCore.QPoint(0, 0)), QtCore.QPoint(0, 0), QtCore.QPoint(0, 200), 200, QtCore.Qt.Vertical, QtCore.Qt.NoButton, QtCore.Qt.NoModifier, QtCore.Qt.ScrollUpdate) # dispatch event self.window._on_mouse_wheel(qt_event) # validate results self.assertEqual(self.tool.event.mouse_wheel_axis, 'vertical') self.assertEqual(self.tool.event.mouse_wheel, 5.0 / 3.0) self.assertEqual(self.tool.event.mouse_wheel_delta, (0, 200))
def removeRows(self, row, count, parent=QtCore.QModelIndex()): """ Reimplemented to allow row deletion, as well as reordering via drag and drop. """ editor = self._editor adapter = editor.adapter self.beginRemoveRows(parent, row, row + count - 1) for i in xrange(count): editor.callx(adapter.delete, editor.object, editor.name, row) self.endRemoveRows() return True
def insertRow(self, row, parent=QtCore.QModelIndex(), obj=None): """Reimplemented to allow creation of new rows. Added an optional arg to allow the insertion of an existing row object.""" editor = self._editor if obj is None: obj = editor.create_new_row() self.beginInsertRows(parent, row, row) editor.callx(list(editor.items()).insert, row, obj) self.endInsertRows() return True
def check_date_bgcolor(self, editor, date, expected): from pyface.qt import QtCore qdate = QtCore.QDate(date.year, date.month, date.day) textformat = editor.control.dateTextFormat(qdate) color = textformat.background().color() actual = (color.red(), color.green(), color.blue()) self.assertEqual( actual, expected, "Expected color: {!r}. Got color: {!r}".format( expected, actual, ))
def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ self.control = QtGui.QDateEdit() if hasattr(self.factory, "qt_date_format"): self.control.setDisplayFormat(self.factory.qt_date_format) if not self.factory.allow_future: self.control.setMaximumDate(QtCore.QDate.currentDate()) if getattr(self.factory, "maximum_date_name", None): obj, extended_name, func = self.parse_extended_name( self.factory.maximum_date_name ) self.factory.maximum_date = func() if getattr(self.factory, "minimum_date_name", None): obj, extended_name, func = self.parse_extended_name( self.factory.minimum_date_name ) self.factory.minimum_date = func() if getattr(self.factory, "minimum_date", None): min_date = QtCore.QDate( self.factory.minimum_date.year, self.factory.minimum_date.month, self.factory.minimum_date.day, ) self.control.setMinimumDate(min_date) if getattr(self.factory, "maximum_date", None): max_date = QtCore.QDate( self.factory.maximum_date.year, self.factory.maximum_date.month, self.factory.maximum_date.day, ) self.control.setMaximumDate(max_date) self.control.dateChanged.connect(self.update_object)
def event_loop_until_condition(self, condition, timeout=10.0): """Runs the real Qt event loop until the provided condition evaluates to True. Raises ConditionTimeoutError if the timeout occurs before the condition is satisfied. Parameters ---------- condition : callable A callable to determine if the stop criteria have been met. This should accept no arguments. timeout : float Number of seconds to run the event loop in the case that the trait change does not occur. """ def handler(): if condition(): self.qt_app.quit() # Make sure we don't get a premature exit from the event loop. with dont_quit_when_last_window_closed(self.qt_app): condition_timer = QtCore.QTimer() condition_timer.setInterval(50) condition_timer.timeout.connect(handler) timeout_timer = QtCore.QTimer() timeout_timer.setSingleShot(True) timeout_timer.setInterval(timeout * 1000) timeout_timer.timeout.connect(self.qt_app.quit) timeout_timer.start() condition_timer.start() try: self.qt_app.exec_() if not condition(): raise ConditionTimeoutError( 'Timed out waiting for condition') finally: timeout_timer.stop() condition_timer.stop()
def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ self.icon = QtGui.QIcon(self.factory.filename) if self.factory.toggle_filename: self.toggled_icon = QtGui.QIcon(self.factory.toggle_filename) if self.factory.toggle_label != '': self.toggle_label = self.factory.toggle_label else: self.toggle_label = self.factory.label if self.factory.toggle_tooltip != '': self.toggle_tooltip = self.factory.toggle_tooltip else: self.toggle_tooltip = self.factory.tooltip control = self.control = QtGui.QToolButton() control.setAutoRaise(True) control.setIcon(self.icon) control.setText(self.factory.label) control.setIconSize( QtCore.QSize(self.factory.width, self.factory.height)) if self.factory.label: control.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) else: control.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) if self.factory.toggle: control.setCheckable(True) control.toggled.connect(self._toggle_button) QtCore.QObject.connect(control, QtCore.SIGNAL('clicked()'), self.update_object) if self.factory.tooltip: control.setToolTip(self.factory.tooltip) else: self.set_tooltip()
def wait_for_qt_signal(qt_signal, timeout): """ Wait for the given Qt signal to fire, or timeout. A mock implementation of QSignalSpy.wait, which is one of the missing bindings in PySide2, and is not available in Qt4. Parameters ---------- qt_signal : signal Qt signal to wait for timeout : int Timeout in milliseconds, to match Qt API. Raises ------ RuntimeError """ from pyface.qt import QtCore # QEventLoop is used instead of QApplication due to observed # hangs with Qt4. event_loop = QtCore.QEventLoop() def exit(*args, **kwargs): event_loop.quit() timeout_timer = QtCore.QTimer() timeout_timer.setSingleShot(True) timeout_timer.setInterval(timeout) timeout_timer.timeout.connect(exit) qt_signal.connect(exit) timeout_timer.start() event_loop.exec_() qt_signal.disconnect(exit) if timeout_timer.isActive(): timeout_timer.stop() else: raise RuntimeError("Timeout waiting for signal.")
def test_horizontal_mouse_wheel(self): from pyface.qt import QtCore, QtGui, is_qt4, is_qt5 # create and mock a mouse wheel event if is_qt4: qt_event = QtGui.QWheelEvent( QtCore.QPoint(0, 0), # pos 200, # delta QtCore.Qt.NoButton, # buttons QtCore.Qt.NoModifier, # modifiers QtCore.Qt.Horizontal, # orient ) elif is_qt5: qt_event = QtGui.QWheelEvent( QtCore.QPoint(0, 0), # pos self.window.control.mapToGlobal(QtCore.QPoint(0, 0)), # globalPos QtCore.QPoint(200, 0), # pixelDelta QtCore.QPoint(200, 0), # angleDelta 200, # qt4Delta QtCore.Qt.Horizontal, # qt4Orietation QtCore.Qt.NoButton, # buttons QtCore.Qt.NoModifier, # modifiers QtCore.Qt.ScrollUpdate, # phase ) else: qt_event = QtGui.QWheelEvent( QtCore.QPointF(0, 0), # pos self.window.control.mapToGlobal(QtCore.QPointF( 0, 0)), # globalPos QtCore.QPoint(200, 0), # pixelDelta QtCore.QPoint(200, 0), # angleDelta QtCore.Qt.NoButton, # buttons QtCore.Qt.NoModifier, # modifiers QtCore.Qt.ScrollUpdate, # phase False, # inverted ) # dispatch event self.window._on_mouse_wheel(qt_event) # validate results self.assertEqual(self.tool.event.mouse_wheel_axis, "horizontal") self.assertAlmostEqual(self.tool.event.mouse_wheel, 5.0 / 3.0) self.assertEqual(self.tool.event.mouse_wheel_delta, (200, 0))
def __init__(self, is_image=False, bgcolor="white", image_default_origin="top left", *args, **kw): if 'size' in kw and isinstance(kw['size'], tuple): # Convert to a QSize. kw['size'] = QtCore.QSize(*kw['size']) super(PlotWindow, self).__init__(None, *args, **kw) # Some defaults which should be overridden by preferences. self.bgcolor = bgcolor self.image_default_origin = image_default_origin # Create an empty top-level container if is_image: top_container = self._create_top_img_container() else: top_container = self._create_top_container() # The PlotSession of which we are a part. We need to know this in order # to notify it of our being closed, etc. self.session = None # Create the Enable Window object, and store a reference to it. # (This will be handy later.) The Window requires a parent object # as its first argument, so we just pass 'self'. self.plot_window = Window(self, component=top_container) layout = QtGui.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.plot_window.control) self.setLayout(layout) size = kw.get("size", QtCore.QSize(600, 600)) self.set_size(size.width(), size.height()) self.show()
def create(self, parent): """ Create and set the toolkit-specific control that represents the pane. """ # Create and configure the tab widget. self.control = control = EditorAreaWidget(self, parent) self._filter = EditorAreaDropFilter(self) control.installEventFilter(self._filter) control.tabBar().setVisible(not self.hide_tab_bar) # Connect to the widget's signals. control.currentChanged.connect(self._update_active_editor) self._connections_to_remove.append( (control.currentChanged, self._update_active_editor)) control.tabCloseRequested.connect(self._close_requested) self._connections_to_remove.append( (control.tabCloseRequested, self._close_requested)) # Add shortcuts for scrolling through tabs. if sys.platform == "darwin": next_seq = "Ctrl+}" prev_seq = "Ctrl+{" else: next_seq = "Ctrl+PgDown" prev_seq = "Ctrl+PgUp" shortcut = QtGui.QShortcut(QtGui.QKeySequence(next_seq), self.control) shortcut.activated.connect(self._next_tab) self._connections_to_remove.append( (shortcut.activated, self._next_tab)) shortcut = QtGui.QShortcut(QtGui.QKeySequence(prev_seq), self.control) shortcut.activated.connect(self._previous_tab) self._connections_to_remove.append( (shortcut.activated, self._previous_tab)) # Add shortcuts for switching to a specific tab. mod = "Ctrl+" if sys.platform == "darwin" else "Alt+" mapper = QtCore.QSignalMapper(self.control) if is_pyside and is_qt6: mapper.mappedInt.connect(self.control.setCurrentIndex) self._connections_to_remove.append( (mapper.mappedInt, self.control.setCurrentIndex)) else: mapper.mapped.connect(self.control.setCurrentIndex) self._connections_to_remove.append( (mapper.mapped, self.control.setCurrentIndex)) for i in range(1, 10): sequence = QtGui.QKeySequence(mod + str(i)) shortcut = QtGui.QShortcut(sequence, self.control) shortcut.activated.connect(mapper.map) self._connections_to_remove.append( (shortcut.activated, mapper.map)) mapper.setMapping(shortcut, i - 1)
def _create_buttons(self, dialog, layout): """ Creates the buttons. """ if not (self.can_cancel or self.can_ok): return # Create the button. buttons = QtGui.QDialogButtonBox() if self.can_cancel: buttons.addButton(self.cancel_button_label, QtGui.QDialogButtonBox.RejectRole) if self.can_ok: buttons.addButton(QtGui.QDialogButtonBox.Ok) # TODO: hookup the buttons to our methods, this may involve subclassing from QDialog if self.can_cancel: buttons.connect(buttons, QtCore.SIGNAL('rejected()'), dialog, QtCore.SLOT('reject()')) if self.can_ok: buttons.connect(buttons, QtCore.SIGNAL('accepted()'), dialog, QtCore.SLOT('accept()')) layout.addWidget(buttons)
def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ super(ListEditor, self).init(parent) self.control = QtGui.QListWidget() QtCore.QObject.connect(self.control, QtCore.SIGNAL('currentTextChanged(QString)'), self.update_object) self.rebuild_editor() self.set_tooltip()
# Plugin imports. from envisage.core_plugin import CorePlugin from envisage.ui.tasks.tasks_plugin import TasksPlugin from plugin import HelmholtzVisPlugin # XXX: Hide warnings from Qt about setting negative sizes. These are harmless # and I don't have time to track them down. if ETSConfig.toolkit == 'qt4': def warning_filter(msg_type, msg): if msg_type == QtCore.QtWarningMsg and 'negative size' in msg.lower(): return print(msg, file=sys.stderr) from pyface.qt import QtCore QtCore.qInstallMsgHandler(warning_filter) class HelmholtzVisApplication(TasksApplication): #### 'IApplication' interface ############################################# # The application's globally unique identifier. id = 'neural.helmholtz_vis' # The application's user-visible name. name = 'Helmholtz Machine' #### 'TasksApplication' interface ######################################### # The default window-level layout for the application.