def readSettings(self, settings): qapp = QApplication.instance() qapp.setAttribute(Qt.AA_UseHighDpiPixmaps) if hasattr(Qt, 'AA_EnableHighDpiScaling'): qapp.setAttribute(Qt.AA_EnableHighDpiScaling, settings.get('high_dpi_scaling')) # get the saved window geometry window_size = settings.get('MainWindow/size') if not isinstance(window_size, QSize): window_size = QSize(*window_size) window_pos = settings.get('MainWindow/position') if not isinstance(window_pos, QPoint): window_pos = QPoint(*window_pos) # make sure main window is smaller than the desktop desktop = QDesktopWidget() # this gives the maximum screen number if the position is off screen screen = desktop.screenNumber(window_pos) # recalculate the window size desktop_geom = desktop.screenGeometry(screen) w = min(desktop_geom.size().width(), window_size.width()) h = min(desktop_geom.size().height(), window_size.height()) window_size = QSize(w, h) # and position it on the supplied desktop screen x = max(window_pos.x(), desktop_geom.left()) y = max(window_pos.y(), desktop_geom.top()) window_pos = QPoint(x, y) # set the geometry self.resize(window_size) self.move(window_pos) # restore window state if settings.has('MainWindow/state'): self.restoreState(settings.get('MainWindow/state')) else: self.setWindowState(Qt.WindowMaximized) # read in settings for children AlgorithmInputHistory().readSettings(settings) for widget in self.widgets: if hasattr(widget, 'readSettings'): widget.readSettings(settings)
def presentError(self, widget, error): assert isinstance(widget, QWidget) self._error_widget.setText(ErrorPopup.error_template % html.escape(error)) self.show() size_hint = self.sizeHint() rect = widget.rect() p = widget.mapToGlobal(QPoint(rect.left(), rect.top())) self.setGeometry(p.x(), p.y() - size_hint.height() - 5, size_hint.width(), size_hint.height()) self.raise_()
def show_menu(self): """Display a menu when clicking on the widget.""" menu = self.menu menu.clear() text = _("Change default environment in Preferences...") change_action = create_action( self, text=text, triggered=self.open_interpreter_preferences, ) add_actions(menu, [change_action]) rect = self.contentsRect() os_height = 7 if os.name == 'nt' else 12 pos = self.mapToGlobal(rect.topLeft() + QPoint(-40, -rect.height() - os_height)) menu.popup(pos)
def selectRow(self, row, modifier): """ Select a full row by clicking on its header. Args: row (int): row index modifier (Qt::KeyboardModifier): modifier key """ # find the middle of the row header vertical_header = self.view.table.verticalHeader() x = 0 + vertical_header.length() / 2 y = vertical_header.sectionPosition(row) \ + vertical_header.sectionSize(row) / 2 QTest.mouseClick(vertical_header.viewport(), Qt.LeftButton, modifier, QPoint(x, y))
def selectColumn(self, column, modifier): """ Select a full column by clicking on its header. Args: column (int): column index modifier (Qt::KeyboardModifier): modifier key """ # find the middle of the column header horizontal_header = self.view.table.horizontalHeader() x = horizontal_header.sectionPosition(column) \ + horizontal_header.sectionSize(column) / 2 y = 0 + horizontal_header.length() / 2 QTest.mouseClick(horizontal_header.viewport(), Qt.LeftButton, modifier, QPoint(x, y))
def warn(widget, text=None): """Display warning for widget in preferences.""" label = widget.label_information if text: pixmap = QPixmap(WARNING_ICON) label.setPixmap( pixmap.scaled(16, 16, Qt.KeepAspectRatio, Qt.SmoothTransformation)) label.setToolTip(str(text)) w = widget.label_information.width() / 2 h = widget.label_information.height() / 2 position = widget.label_information.mapToGlobal(QPoint(w, h)) QCursor.setPos(position) else: label.setPixmap(QPixmap()) label.setToolTip('')
def __updateRGBACrosshairOnResize(self): """ Updates the RGBA crosshair to the correct position. """ rgba_crosshair_pos = self.scene().getRGBACrosshairPos() old_width = self.getPreviousSize().width() old_height = self.getPreviousSize().height() crosshair_xpos = rgba_crosshair_pos.x() / old_width crosshair_ypos = rgba_crosshair_pos.y() / old_height # get new crosshair position xpos = crosshair_xpos * self.geometry().width() ypos = crosshair_ypos * self.geometry().height() new_pos = QPoint(xpos, ypos) self.scene().setRGBACrosshairPos(new_pos)
def test_sort_by_column(qtbot): """ Test that clicking the header view the namespacebrowser is sorted. Regression test for spyder-ide/spyder#9835 . """ browser = NamespaceBrowser(None) qtbot.addWidget(browser) browser.set_shellwidget(Mock()) browser.setup() browser.set_data({ 'a_variable': { 'type': 'int', 'size': 1, 'view': '1', 'python_type': 'int', 'numpy_type': 'Unknown' }, 'b_variable': { 'type': 'int', 'size': 1, 'view': '2', 'python_type': 'int', 'numpy_type': 'Unknown' } }) header = browser.editor.horizontalHeader() # Check header is clickable assert header.sectionsClickable() model = browser.editor.model # Base check of the model assert model.rowCount() == 2 assert model.columnCount() == 5 assert data_table(model, 2, 4) == [['a_variable', 'b_variable'], ['int', 'int'], [1, 1], ['1', '2']] with qtbot.waitSignal(header.sectionClicked): browser.show() qtbot.mouseClick(header.viewport(), Qt.LeftButton, pos=QPoint(1, 1)) # Check sort effect assert data_table(model, 2, 4) == [['b_variable', 'a_variable'], ['int', 'int'], [1, 1], ['2', '1']]
def _locate_tip_box(self): """ """ dockwidgets = self.dockwidgets # Store the dimensions of the main window geo = self.parent.frameGeometry() x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height() self.width_main = width self.height_main = height self.x_main = x self.y_main = y delta = 20 # Here is the tricky part to define the best position for the # tip widget if dockwidgets is not None: if dockwidgets[0] is not None: geo = dockwidgets[0].geometry() x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height() point = dockwidgets[0].mapToGlobal(QPoint(0, 0)) x_glob, y_glob = point.x(), point.y() # Check if is too tall and put to the side y_fac = (height / self.height_main) * 100 if y_fac > 60: # FIXME: if x < self.tips.width(): x = x_glob + width + delta y = y_glob + height/2 - self.tips.height()/2 else: x = x_glob - self.tips.width() - delta y = y_glob + height/2 - self.tips.height()/2 else: if y < self.tips.height(): x = x_glob + width/2 - self.tips.width()/2 y = y_glob + height + delta else: x = x_glob + width/2 - self.tips.width()/2 y = y_glob - delta - self.tips.height() else: # Center on parent x = self.x_main + self.width_main/2 - self.tips.width()/2 y = self.y_main + self.height_main/2 - self.tips.height()/2 self.tips.set_pos(x, y)
def _readViewSettings(self, reset=False): """ Reads the persistent program settings. :param reset: If True, the program resets to its default settings. """ pos = QPoint(20, 20) window_size = QSize(825, 650) details_button_idx = 0 header = self.obj_tree.header() header_restored = False if reset: logger.debug("Resetting persistent view settings") else: pos = pos window_size = window_size details_button_idx = details_button_idx # splitter_state = settings.value("central_splitter/state") splitter_state = None if splitter_state: self.central_splitter.restoreState(splitter_state) # header_restored = self.obj_tree.read_view_settings( # 'table/header_state', # settings, reset) header_restored = False if not header_restored: column_sizes = [col.width for col in self._attr_cols] column_visible = [col.col_visible for col in self._attr_cols] for idx, size in enumerate(column_sizes): if not self._resize_to_contents and size > 0: # Just in case header.resizeSection(idx, size) else: header.setSectionResizeMode(QHeaderView.ResizeToContents) for idx, visible in enumerate(column_visible): elem = self.obj_tree.toggle_column_actions_group.actions()[idx] elem.setChecked(visible) self.resize(window_size) button = self.button_group.button(details_button_idx) if button is not None: button.setChecked(True)
def show_calltip(self, title, text, signature=False, color='#2D62FF', at_line=None, at_position=None, at_point=None): """Show calltip""" if text is None or len(text) == 0: return # Saving cursor position: if at_position is None: at_position = self.get_position('cursor') self.calltip_position = at_position # Preparing text: if signature: text, wrapped_textlines = self._format_signature(text) else: if isinstance(text, list): text = "\n ".join(text) text = text.replace('\n', '<br>') if len(text) > self.calltip_size: text = text[:self.calltip_size] + " ..." # Formatting text font = self.font() size = font.pointSize() family = font.family() format1 = '<div style=\'font-family: "%s"; font-size: %spt; color: %s\'>'\ % (family, size, color) format2 = '<div style=\'font-family: "%s"; font-size: %spt\'>'\ % (family, size-1 if size > 9 else size) tiptext = format1 + ('<b>%s</b></div>' % title) + '<hr>' + \ format2 + text + "</div>" # Showing tooltip at cursor position: cx, cy = self.get_coordinates('cursor') if at_point is not None: cx, cy = at_point.x(), at_point.y() if at_line is not None: cx = 5 cursor = QTextCursor(self.document().findBlockByNumber(at_line-1)) cy = self.cursorRect(cursor).top() point = self.mapToGlobal(QPoint(cx, cy)) point = self.calculate_real_position(point) point.setY(point.y()+font.pointSize()+5) if signature: self.calltip_widget.show_tip(point, tiptext, wrapped_textlines) else: QToolTip.showText(point, tiptext)
def readSettings(self, settings): qapp = QApplication.instance() # get the saved window geometry window_size = settings.get('MainWindow/size') if not isinstance(window_size, QSize): window_size = QSize(*window_size) window_pos = settings.get('MainWindow/position') if not isinstance(window_pos, QPoint): window_pos = QPoint(*window_pos) if settings.has('MainWindow/font'): font_string = settings.get('MainWindow/font').split(',') font = QFontDatabase().font(font_string[0], font_string[-1], int(font_string[1])) qapp.setFont(font) # make sure main window is smaller than the desktop desktop = QDesktopWidget() # this gives the maximum screen number if the position is off screen screen = desktop.screenNumber(window_pos) # recalculate the window size desktop_geom = desktop.availableGeometry(screen) w = min(desktop_geom.size().width(), window_size.width()) h = min(desktop_geom.size().height(), window_size.height()) window_size = QSize(w, h) # and position it on the supplied desktop screen x = max(window_pos.x(), desktop_geom.left()) y = max(window_pos.y(), desktop_geom.top()) if x + w > desktop_geom.right(): x = desktop_geom.right() - w if y + h > desktop_geom.bottom(): y = desktop_geom.bottom() - h window_pos = QPoint(x, y) # set the geometry self.resize(window_size) self.move(window_pos) # restore window state if settings.has('MainWindow/state'): if not self.restoreState(settings.get('MainWindow/state'), SAVE_STATE_VERSION): logger.warning( "The previous layout of workbench is not compatible with this version, reverting to default layout." ) else: self.setWindowState(Qt.WindowMaximized) # read in settings for children AlgorithmInputHistory().readSettings(settings) for widget in self.widgets: if hasattr(widget, 'readSettingsIfNotDone'): widget.readSettingsIfNotDone(settings)
def context_menu_requested(self, event): """Popup context menu.""" if self.fig: pos = QPoint(event.x(), event.y()) context_menu = QMenu(self) context_menu.addAction( ima.icon('filesave'), _("Save plot as..."), lambda: self.sig_save_fig_requested.emit(), QKeySequence(CONF.get_shortcut('plots', 'save'))) context_menu.addAction( ima.icon('editcopy'), _("Copy Image"), self.copy_figure, QKeySequence(CONF.get_shortcut('plots', 'copy'))) context_menu.addAction( ima.icon('editclear'), _("Remove plot"), lambda: self.sig_clear_fig_requested.emit(), QKeySequence(CONF.get_shortcut('plots', 'close'))) context_menu.popup(self.mapToGlobal(pos))
def test_keys_sorted_and_sort_with_large_rows(qtbot): """ Test that keys are sorted and sorting works as expected when there's a large number of rows. This is a regression test for issue spyder-ide/spyder#10702 """ browser = NamespaceBrowser(None) qtbot.addWidget(browser) browser.set_shellwidget(Mock()) browser.setup() # Create variables. variables = {} variables['i'] = ( {'type': 'int', 'size': 1, 'color': '#0000ff', 'view': '1'} ) for i in range(100): if i < 10: var = 'd_0' + str(i) else: var = 'd_' + str(i) variables[var] = ( {'type': 'int', 'size': 1, 'color': '#0000ff', 'view': '1'} ) # Set data browser.set_data(variables) # Assert we loaded the expected amount of data and that we can fetch # more. model = browser.editor.model assert model.rowCount() == ROWS_TO_LOAD assert model.canFetchMore(QModelIndex()) # Assert keys are sorted assert data(model, 49, 0) == 'd_49' # Sort header = browser.editor.horizontalHeader() with qtbot.waitSignal(header.sectionClicked): qtbot.mouseClick(header.viewport(), Qt.LeftButton, pos=QPoint(1, 1)) # Assert we loaded all data before performing the sort. assert data(model, 0, 0) == 'i'
def selectCell(self, row, column, modifier): """ Select a cell by clicking on it. Args: row (int): row index column (int): column index modifier (Qt::KeyboardModifier): modifier key """ # find the middle of the cell y = self.view.table.rowViewportPosition(row) \ + self.view.table.rowHeight(row) / 2 x = self.view.table.columnViewportPosition(column) \ + self.view.table.columnWidth(column) / 2 QTest.mouseClick(self.view.table.viewport(), Qt.LeftButton, modifier, QPoint(x, y))
def test_goto_uri_project_root_path(qtbot, codeeditor, mocker, tmpdir): """Test that the uri search is working correctly.""" code_editor = codeeditor code_editor.show() mock_project_dir = str(tmpdir) expected_output_path = os.path.join(mock_project_dir, "some-file.txt") with open(expected_output_path, "w") as fh: fh.write("BOOM!\n") code_editor.set_current_project_path(mock_project_dir) code_editor.filename = "foo.txt" mocker.patch.object(QDesktopServices, 'openUrl') # Set text in editor code_editor.set_text("file://^/some-file.txt") # Get cursor coordinates code_editor.moveCursor(QTextCursor.Start) x, y = code_editor.get_coordinates('cursor') # The `+ 23` is to put the mouse on top of the word point = code_editor.calculate_real_position(QPoint(x + 23, y)) # Move cursor to end of line code_editor.moveCursor(QTextCursor.End) # Move mouse cursor on top of test word qtbot.mouseMove(code_editor, point, delay=500) # Check valid with project open with qtbot.waitSignal(code_editor.sig_file_uri_preprocessed, timeout=3000) as blocker: qtbot.keyPress(code_editor, Qt.Key_Control, delay=500) args = blocker.args assert args[0] == expected_output_path qtbot.wait(500) # Check with project closed expected_output_path = os.path.expanduser("~/some-file.txt") code_editor.set_current_project_path() with qtbot.waitSignal(code_editor.sig_file_uri_preprocessed, timeout=3000) as blocker: qtbot.keyPress(code_editor, Qt.Key_Control, delay=500) args = blocker.args assert args[0] == expected_output_path
def hoverMoveEvent(self, event: QGraphicsSceneHoverEvent): """ hoverMoveEvent Parameters ---------- q_graphics_scene_hover_event : QGraphicsSceneHoverEvent """ pos = event.pos() geom = self._node.geometry if (self._node.model.resizable() and geom.resize_rect.contains(QPoint(pos.x(), pos.y()))): self.setCursor(QCursor(Qt.SizeFDiagCursor)) else: self.setCursor(QCursor()) event.accept()
def set_window_settings(self, hexstate, window_size, prefs_dialog_size, pos, is_maximized, is_fullscreen): """ Set window settings Symetric to the 'get_window_settings' accessor. """ main = self.main main.setUpdatesEnabled(False) self.prefs_dialog_size = QSize(prefs_dialog_size[0], prefs_dialog_size[1]) # width,height main.set_prefs_size(self.prefs_dialog_size) self.window_size = QSize(window_size[0], window_size[1]) # width, height self.window_position = QPoint(pos[0], pos[1]) # x,y main.setWindowState(Qt.WindowNoState) main.resize(self.window_size) main.move(self.window_position) # Window layout if hexstate: hexstate_valid = self.main.restoreState( QByteArray().fromHex(str(hexstate).encode('utf-8')), version=WINDOW_STATE_VERSION ) # Check layout validity. Spyder 4 and below use the version 0 # state (default), whereas Spyder 5 will use version 1 state. # For more info see the version argument for # QMainWindow.restoreState: # https://doc.qt.io/qt-5/qmainwindow.html#restoreState if not hexstate_valid: self.main.setUpdatesEnabled(True) self.setup_layout(default=True) return # Is fullscreen? if is_fullscreen: self.main.setWindowState(Qt.WindowFullScreen) # Is maximized? if is_fullscreen: self._maximized_flag = is_maximized elif is_maximized: self.main.setWindowState(Qt.WindowMaximized) self.main.setUpdatesEnabled(True)
def dragEnterEvent(self, event): _log.debug("TabContainer: Drag enter event") if not self.__checkEventMimeTypeData(event): return data = event.mimeData().data(MIME_TYPE).data() dock_uid = pickle.loads(data) _log.debug("ETID: {}".format(dock_uid)) for d in self.flatDockList: if d.uid == dock_uid and len(self.flatDockList) == 1: _log.debug("Tab in container") event.ignore() return if self.rect().width() < 200 and self.rect().height() < 200: _log.debug("To less widget left...") event.ignore() return if self.overlay.isHidden(): _log.debug("Drop overlay") self.overlay.raise_() self.overlay.show() w = self._dockstack.currentWidget() pos = w.mapTo(self, QPoint(0, 0)) rect = QRect(pos.x(), pos.y(), w.width(), w.height()) self.overlay.setGeometry(rect) xc = pos.x() + w.width() / 2.0 yc = pos.y() + w.height() / 2.0 self.refDropRegions = { TabContainer.Point(xc - 34, yc): Placement.LEFT, TabContainer.Point(xc + 34, yc): Placement.RIGHT, TabContainer.Point(xc, yc - 34): Placement.TOP, TabContainer.Point(xc, yc + 34): Placement.BOTTOM, TabContainer.Point(xc, yc): Placement.TAB, } self.absDropRegions = { TabContainer.Point(xc - 68, yc): Placement.LEFT, TabContainer.Point(xc + 68, yc): Placement.RIGHT, TabContainer.Point(xc, yc - 68): Placement.TOP, TabContainer.Point(xc, yc + 68): Placement.BOTTOM, }
def mousePressEvent(self, event): """Override Qt method.""" QTableView.mousePressEvent(self, event) pos = QPoint(event.x(), event.y()) index = self.indexAt(pos) model = self.source_model if self.proxy_model is None or self.source_model is None: return model_index = self.proxy_model.mapToSource(index) row = model_index.row() if row == -1: return column = model_index.column() row_data = self.source_model.row(row) remove_actions = self.source_model.count_remove_actions() # install_actions = self.source_model.count_install_actions() action = row_data[C.COL_ACTION] status = row_data[C.COL_STATUS] right_click = event.button() == Qt.RightButton left_click = event.button() == Qt.LeftButton if column == C.COL_ACTION: if right_click or (left_click and status != C.NOT_INSTALLED): self.context_menu_requested(event) elif left_click and status == C.NOT_INSTALLED: # 1-click install/uncheck if not installed if action == C.ACTION_NONE and not remove_actions: self.set_action_status(model_index, C.ACTION_INSTALL) elif status: self.set_action_status(model_index, C.ACTION_NONE) elif (column == C.COL_VERSION and model.is_upgradable(model_index) and left_click): # 1-click update name = row_data[C.COL_NAME] versions = model.get_package_versions(name) self.set_action_status(model_index, C.ACTION_UPGRADE, versions[-1]) self.update_visible_rows()
def test_get_hints_not_triggered(qtbot, lsp_codeeditor): """Test that the editor is not returning hover hints for empty docs.""" code_editor, _ = lsp_codeeditor # Set text in editor code_editor.set_text('def test():\n pass\n\ntest') # Get cursor coordinates code_editor.moveCursor(QTextCursor.End) qtbot.keyPress(code_editor, Qt.Key_Left) x, y = code_editor.get_coordinates('cursor') point = code_editor.calculate_real_position(QPoint(x, y)) with qtbot.waitSignal(code_editor.sig_display_object_info, timeout=30000): qtbot.mouseMove(code_editor, point) qtbot.mouseClick(code_editor, Qt.LeftButton, pos=point) qtbot.wait(1000) assert not code_editor.tooltip_widget.isVisible()
def test_contextMenuEvent_calls_exec(view_and_model, monkeypatch): # test that a menu is displayed when clicking on an item mock_exec = Mock() monkeypatch.setattr('spyder_unittest.widgets.datatree.QMenu.exec_', mock_exec) view, model = view_and_model pos = view.visualRect(model.index(0, 0)).center() event = QContextMenuEvent(QContextMenuEvent.Mouse, pos) view.contextMenuEvent(event) assert mock_exec.called # test that no menu is displayed when clicking below the bottom item mock_exec.reset_mock() pos = view.visualRect(model.index(1, 0)).bottomRight() pos += QPoint(0, 1) event = QContextMenuEvent(QContextMenuEvent.Mouse, pos) view.contextMenuEvent(event) assert not mock_exec.called
def readSettings(self, settings): qapp = QApplication.instance() qapp.setAttribute(Qt.AA_UseHighDpiPixmaps) if hasattr(Qt, 'AA_EnableHighDpiScaling'): qapp.setAttribute(Qt.AA_EnableHighDpiScaling, settings.get('high_dpi_scaling')) # get the saved window geometry window_size = settings.get('MainWindow/size') if not isinstance(window_size, QSize): window_size = QSize(*window_size) window_pos = settings.get('MainWindow/position') if not isinstance(window_pos, QPoint): window_pos = QPoint(*window_pos) if settings.has('MainWindow/font'): font_string = settings.get('MainWindow/font').split(',') font = QFontDatabase().font(font_string[0], font_string[-1], int(font_string[1])) qapp.setFont(font) # make sure main window is smaller than the desktop desktop = QDesktopWidget() # this gives the maximum screen number if the position is off screen screen = desktop.screenNumber(window_pos) # recalculate the window size desktop_geom = desktop.screenGeometry(screen) w = min(desktop_geom.size().width(), window_size.width()) h = min(desktop_geom.size().height(), window_size.height()) window_size = QSize(w, h) # and position it on the supplied desktop screen x = max(window_pos.x(), desktop_geom.left()) y = max(window_pos.y(), desktop_geom.top()) window_pos = QPoint(x, y) # set the geometry self.resize(window_size) self.move(window_pos) # restore window state if settings.has('MainWindow/state'): self.restoreState(settings.get('MainWindow/state')) else: self.setWindowState(Qt.WindowMaximized) # read in settings for children AlgorithmInputHistory().readSettings(settings) for widget in self.widgets: if hasattr(widget, 'readSettings'): widget.readSettings(settings)
def drawline(self, p1, p2, angle, tip=False): painter = QPainter() painter.begin(self) painter.setRenderHint(QPainter.Antialiasing) painter.setPen(Qt.blue) pen = painter.pen() pen.setWidth(2) painter.setPen(pen) painter.setBrush(Qt.blue) painter.translate(p1) painter.rotate(angle) pt = (p2 - p1) if tip: pt /= (pt.x()**2 + pt.y()**2)**0.5 / 10 # painter.scale(scale, scale) # painter.drawLine(QPoint(0, 0), (p2-p1)*scale) painter.drawLine(QPoint(0, 0), pt) return painter
def test_collectionseditor_when_clicking_on_header_and_large_rows(qtbot): """ Test that sorting works when clicking in its header and there's a large number of rows. """ li = [1] * 10000 editor = CollectionsEditor() editor.setup(li) # Perform the sorting. It should be done quite quickly because # there's a very small number of rows in display. view = editor.widget.editor header = view.horizontalHeader() with qtbot.waitSignal(header.sectionClicked, timeout=200): qtbot.mouseClick(header.viewport(), Qt.LeftButton, pos=QPoint(1, 1)) # Assert data was sorted correctly. assert data(view.model, 0, 0) == 9999
def start_tour(self): """ """ geo = self.parent.geometry() x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height() # self.parent_x = x # self.parent_y = y # self.parent_w = width # self.parent_h = height # FIXME: reset step to last used value # Reset step to begining self.step_current = self.last_frame_active # Adjust the canvas size to match the main window size self.canvas.setFixedSize(width, height) self.canvas.move(QPoint(x, y)) self.canvas.fade_in(self._move_step) self._clear_canvas()
def paint(self, painter, option, index): options = QStyleOptionViewItem(option) self.initStyleOption(options, index) style = (QApplication.style() if options.widget is None else options.widget.style()) # Set background color for selected and hovered items. # Inspired by: # - https://stackoverflow.com/a/43253004/438386 # - https://stackoverflow.com/a/27274233/438386 # This is commented for now until we find a way to correctly colorize # the entire line with a single color. # if options.state & QStyle.State_Selected: # # This only applies when the selected item doesn't have focus # if not (options.state & QStyle.State_HasFocus): # options.palette.setBrush( # QPalette.Highlight, # QBrush(self._background_color) # ) if options.state & QStyle.State_MouseOver: painter.fillRect(option.rect, self._background_color) # Set text doc = QTextDocument() text = options.text doc.setHtml(text) doc.setDocumentMargin(0) # This needs to be an empty string to avoid overlapping the # normal text of the QTreeWidgetItem options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options, None) painter.save() painter.translate(textRect.topLeft() + QPoint(0, 4)) doc.documentLayout().draw(painter, ctx) painter.restore()
def render(self): rect = QRect(QPoint(), self.geometry().size()) self.m_backingStore.resize(rect.size()) self.m_backingStore.beginPaint(QRegion(rect)) device = self.m_backingStore.paintDevice() p = QPainter(device) p.drawImage(0, 0, self.m_image) font = QFont() font.setPixelSize(32) p.setFont(font) p.drawText(rect, 0, self.m_text) self.m_backingStore.endPaint() self.m_backingStore.flush(QRegion(rect))
def test_sort_by_column(qtbot): """ Test that clicking the header view the namespacebrowser is sorted. Regression test for spyder-ide/spyder#9835 . """ browser = NamespaceBrowser(None) qtbot.addWidget(browser) browser.set_shellwidget(Mock()) browser.setup(exclude_private=True, exclude_uppercase=True, exclude_capitalized=True, exclude_unsupported=False, exclude_callables_and_modules=True, minmax=False) browser.set_data( {'a_variable': {'type': 'int', 'size': 1, 'color': '#0000ff', 'view': '1'}, 'b_variable': {'type': 'int', 'size': 1, 'color': '#0000ff', 'view': '2'}} ) header = browser.editor.horizontalHeader() # Check header is clickable assert header.sectionsClickable() model = browser.editor.model # Base check of the model assert model.rowCount() == 2 assert model.columnCount() == 5 assert data_table(model, 2, 4) == [['a_variable', 'b_variable'], ['int', 'int'], [1, 1], ['1', '2']] with qtbot.waitSignal(header.sectionClicked): browser.show() qtbot.mouseClick(header.viewport(), Qt.LeftButton, pos=QPoint(1, 1)) # Check sort effect assert data_table(model, 2, 4) == [['b_variable', 'a_variable'], ['int', 'int'], [1, 1], ['2', '1']]
def updateDevWidget(self): """Update Slit illustration.""" self.style().unpolish(self.dev_widget.widget_draw) self.style().polish(self.dev_widget.widget_draw) widget_w = self.dev_widget.widget_draw.width() widget_h = self.dev_widget.widget_draw.height() vacuum_chamber_d = 36 # mm if self.orientation == 'H': rect_h = widget_h*3/5 rect_w = rect_h/2 circle_d = rect_w factor = circle_d/vacuum_chamber_d xc = (widget_w/2 - self._slit_center*factor) xw = self._slit_width*factor left = round(xc - rect_w - xw/2) right = round(xc + xw/2) self.dev_widget.PyDMDrawingRectangle_HLeft.resize(rect_w, rect_h) self.dev_widget.PyDMDrawingRectangle_HLeft.move( QPoint(left, (widget_h-rect_h)/2)) self.dev_widget.PyDMDrawingRectangle_HRight.resize(rect_w, rect_h) self.dev_widget.PyDMDrawingRectangle_HRight.move( QPoint(right, (widget_h-rect_h)/2)) elif self.orientation == 'V': rect_w = widget_h*3/5 rect_h = rect_w/2 circle_d = rect_h factor = circle_d/vacuum_chamber_d xc = (widget_h/2 - self._slit_center*factor) xw = self._slit_width*factor up = round(xc - rect_h - xw/2) down = round(xc + xw/2) self.dev_widget.PyDMDrawingRectangle_VUp.resize(rect_w, rect_h) self.dev_widget.PyDMDrawingRectangle_VUp.move( QPoint((widget_w-rect_w)/2, up)) self.dev_widget.PyDMDrawingRectangle_VDown.resize(rect_w, rect_h) self.dev_widget.PyDMDrawingRectangle_VDown.move( QPoint((widget_w-rect_w)/2, down)) self.dev_widget.PyDMDrawingCircle.resize(circle_d, circle_d) self.dev_widget.PyDMDrawingCircle.move(QPoint( (widget_w-circle_d)/2, (widget_h-circle_d)/2)) axis_w = self.dev_widget.axis.width() axis_h = self.dev_widget.axis.height() self.dev_widget.axis.move(QPoint( (widget_w-axis_w), (widget_h-axis_h)))
def _locate_tip_box(self): dockwidgets = self.dockwidgets # Store the dimensions of the main window geo = self.parent.frameGeometry() x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height() self.width_main = width self.height_main = height self.x_main = x self.y_main = y delta = 20 offset = 10 # Here is the tricky part to define the best position for the # tip widget if dockwidgets is not None: if dockwidgets[0] is not None: geo = dockwidgets[0].geometry() x, y, width, height = (geo.x(), geo.y(), geo.width(), geo.height()) point = dockwidgets[0].mapToGlobal(QPoint(0, 0)) x_glob, y_glob = point.x(), point.y() # Put tip to the opposite side of the pane if x < self.tips.width(): x = x_glob + width + delta y = y_glob + height / 2 - self.tips.height() / 2 else: x = x_glob - self.tips.width() - delta y = y_glob + height / 2 - self.tips.height() / 2 if (y + self.tips.height()) > (self.y_main + self.height_main): y = (y - (y + self.tips.height() - (self.y_main + self.height_main)) - offset) else: # Center on parent x = self.x_main + self.width_main / 2 - self.tips.width() / 2 y = self.y_main + self.height_main / 2 - self.tips.height() / 2 self.tips.set_pos(x, y)
def show_list(self, completion_list, position): if position is None: # Somehow the position was not saved. # Hope that the current position is still valid self.position = self.textedit.textCursor().position() elif self.textedit.textCursor().position() < position: # hide the text as we moved away from the position return else: self.position = position # Completions are handled differently for the Internal # console. if not isinstance(completion_list[0], dict): self.is_internal_console = True self.completion_list = completion_list self.clear() icons_map = {CompletionItemKind.PROPERTY: 'attribute', CompletionItemKind.VARIABLE: 'attribute', CompletionItemKind.METHOD: 'method', CompletionItemKind.FUNCTION: 'function', CompletionItemKind.CLASS: 'class', CompletionItemKind.MODULE: 'module', CompletionItemKind.CONSTRUCTOR: 'method', CompletionItemKind.REFERENCE: 'attribute'} for completion in completion_list: if not self.is_internal_console: icon = icons_map.get(completion['kind'], 'no_match') self.addItem( QListWidgetItem(ima.icon(icon), completion['insertText'])) else: # This is used by the Internal console. self.addItem(QListWidgetItem(completion[0])) self.setCurrentRow(0) QApplication.processEvents(QEventLoop.ExcludeUserInputEvents) self.show() self.setFocus() self.raise_() # Retrieving current screen height desktop = QApplication.desktop() srect = desktop.availableGeometry(desktop.screenNumber(self)) screen_right = srect.right() screen_bottom = srect.bottom() point = self.textedit.cursorRect().bottomRight() point = self.textedit.calculate_real_position(point) point = self.textedit.mapToGlobal(point) # Computing completion widget and its parent right positions comp_right = point.x() + self.width() ancestor = self.parent() if ancestor is None: anc_right = screen_right else: anc_right = min([ancestor.x() + ancestor.width(), screen_right]) # Moving completion widget to the left # if there is not enough space to the right if comp_right > anc_right: point.setX(point.x() - self.width()) # Computing completion widget and its parent bottom positions comp_bottom = point.y() + self.height() ancestor = self.parent() if ancestor is None: anc_bottom = screen_bottom else: anc_bottom = min([ancestor.y() + ancestor.height(), screen_bottom]) # Moving completion widget above if there is not enough space below x_position = point.x() if comp_bottom > anc_bottom: point = self.textedit.cursorRect().topRight() point = self.textedit.mapToGlobal(point) point.setX(x_position) point.setY(point.y() - self.height()) if ancestor is not None: # Useful only if we set parent to 'ancestor' in __init__ point = ancestor.mapFromGlobal(point) self.move(point) if not self.is_internal_console: tooltip_point = QPoint(point) tooltip_point.setX(point.x() + self.width()) tooltip_point.setY(point.y() - (3 * self.height()) // 4) for completion in completion_list: completion['point'] = tooltip_point if to_text_string(to_text_string( self.textedit.get_current_word(completion=True))): # When initialized, if completion text is not empty, we need # to update the displayed list: self.update_current() # signal used for testing self.sig_show_completions.emit(completion_list)