def set_icon_size(self, size: int | types.SizeType): if isinstance(size, tuple): size = QtCore.QSize(*size) elif isinstance(size, int): size = QtCore.QSize(size, size) self._size = size self.update()
def _has_children(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()): """Test hasChildren.""" model_types = (QtCore.QAbstractListModel, QtCore.QAbstractTableModel) if isinstance(self._model, model_types): print(parent == QtCore.QModelIndex(), self._model.rowCount()) return parent == QtCore.QModelIndex( ) and self._model.rowCount() > 0 else: return self._model.hasChildren(parent)
def minimumSize(self) -> QtCore.QSize: size = QtCore.QSize() for item in self.items: size = size.expandedTo(item.minimumSize()) margin_width = 2 * self.contentsMargins().top() size += QtCore.QSize(margin_width, margin_width) return size
def _column_count(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()): """Test columnCount. Workaround for the fact that ``columnCount`` is a private method in QAbstractListModel/QAbstractTableModel subclasses. """ if isinstance(self._model, QtCore.QAbstractListModel): return 1 if parent == QtCore.QModelIndex() else 0 else: return self._model.columnCount(parent)
def send_mousepress(widget: QtWidgets.QWidget, key): event = gui.MouseEvent( # type: ignore QtCore.QEvent.Type.MouseButtonRelease, QtCore.QPointF(0, 0), QtCore.QPointF(0, 0), key, QtCore.Qt.MouseButton.NoButton, QtCore.Qt.KeyboardModifier(0), # type: ignore ) widgets.Application.sendEvent(widget, event)
def pixmap(self, size: QtCore.QSize, mode: QtGui.QIcon.Mode, state: QtGui.QIcon.State) -> QtGui.QPixmap: """Return the icon as a pixmap with requested size, mode, and state.""" img = gui.Image(size, QtGui.QImage.Format.Format_ARGB32) img.fill(QtCore.Qt.GlobalColor.transparent) pixmap = QtGui.QPixmap.fromImage( img, QtCore.Qt.ImageConversionFlag.NoFormatConversion) rect = QtCore.QRect(QtCore.QPoint(0, 0), size) self.paint(QtGui.QPainter(pixmap), rect, mode, state) return pixmap
def test_lineseries(qtbot): line = charts.LineSeries() line += QtCore.QPointF(1, 1) line += QtCore.QPointF(2, 2) line[1] = QtCore.QPointF(0, 0) line.get_brush() line.get_pen() with open("data.pkl", "wb") as jar: pickle.dump(line, jar) with open("data.pkl", "rb") as jar: line = pickle.load(jar) del line[1]
def test_settings(qapp): settings = core.Settings("1", "2") settings.clear() settings.set_value("test", "value") assert settings.get("empty") is None assert len(settings) > 0 assert "test" in settings assert settings.get("test") == "value" with core.Settings(settings_id="test") as s: s.set_value("test2", "xx") with settings.write_array("test"): pass with settings.read_array("test"): pass with settings.edit_group("test"): pass with pytest.raises(KeyError): del settings["some value"] with pytest.raises(KeyError): settings.pop("some value2") settings["test2"] = "xyz" assert settings["test2"] == "xyz" settings.setdefault("test3", "abc") assert settings.get("test3") == "abc" del settings["test3"] path = pathlib.Path.cwd() for i in settings: pass settings["test"] = True assert settings["test"] is True settings["test"] = "test" assert settings["test"] == "test" settings["test"] = dict(a="b") assert settings["test"] == dict(a="b") settings["test"] = (1, "b") assert settings["test"] == (1, "b") settings["test"] = QtCore.QByteArray(b"test") assert settings["test"] == QtCore.QByteArray(b"test") settings["test"] = b"test" assert settings["test"] == b"test" settings.set_default_format("ini") assert settings.get_default_format() == "ini" with pytest.raises(InvalidParamError): settings.set_default_format("ino") assert settings.get_scope() == "user" settings.set_path("native", "user", path) with pytest.raises(InvalidParamError): settings.set_path("error", "user", path) with pytest.raises(InvalidParamError): settings.set_path("native", "error", path) s = core.Settings.build_from_dict(dict(a="b"))
def _test_basic(self): """Try to call a number of the basic functions (not all). Make sure the model doesn't outright segfault, testing the functions which make sense. """ assert not self._model.buddy(QtCore.QModelIndex()).isValid() self._model.canFetchMore(QtCore.QModelIndex()) assert self._column_count(QtCore.QModelIndex()) >= 0 self._fetch_more(QtCore.QModelIndex()) flags = self._model.flags(QtCore.QModelIndex()) assert flags == constants.DROP_ENABLED or not flags self._has_children(QtCore.QModelIndex()) has_row = self._model.hasIndex(0, 0) if has_row: cache = None self._model.match(self._model.index(0, 0), -1, cache) self._model.mimeTypes() assert not self._parent(QtCore.QModelIndex()).isValid() assert self._model.rowCount() >= 0 self._model.span(QtCore.QModelIndex()) self._model.supportedDropActions() self._model.roleNames()
def send_mousemove( widget: QtWidgets.QWidget, target: QtCore.QPointF | None = None, delay: int = 0 ): if target is None: target = QtCore.QPointF(0, 0) event = gui.MouseEvent( # type: ignore QtCore.QEvent.Type.MouseButtonRelease, target, QtCore.QPointF(0, 0), QtCore.Qt.MouseButton.NoButton, QtCore.Qt.MouseButton.NoButton, QtCore.Qt.KeyboardModifier(0), # type: ignore ) widgets.Application.sendEvent(widget, event)
def detach_tab(self, index: int, point: types.PointType): """Detach tab by removing its contents and placing them in a DetachedTab window. Args: index (int): index location of the tab to be detached point (QtCore.QPoint): screen pos for creating the new DetachedTab window Returns: None: Description """ # Get the tab content if isinstance(point, tuple): point = QtCore.QPoint(*point) name = self.tabText(index) icon = self.tab_icon(index) if icon is None: icon = self.window().windowIcon() widget = self.widget(index) try: widget_rect = widget.frameGeometry() except AttributeError: return # Create a new detached tab window detached_tab = DetachedTab(name, widget) detached_tab.set_modality("none") detached_tab.set_icon(icon) detached_tab.setGeometry(widget_rect) detached_tab.on_close.connect(self.attach_tab) detached_tab.move(point) detached_tab.show() # Create a reference to maintain access to the detached tab self.detached_tabs[name] = detached_tab
def test_abstracttablemodel(): class Test(core.AbstractTableModel): def rowCount(self, parent=None): return 0 def columnCount(self, parent=None): return 0 model = Test() assert model.rowCount() == 0 assert model.columnCount() == 0 with model.change_layout(): pass with model.reset_model(): pass with model.remove_rows(): pass with model.remove_columns(): pass with model.insert_rows(): pass with model.append_rows(1): pass with model.insert_columns(): pass model.force_reset() model.force_layoutchange() model.check_index( QtCore.QModelIndex(), index_is_valid=True, do_not_use_parent=True, parent_is_invalid=True, )
def _test_row_count_and_column_count(self): """Test model's implementation of row/columnCount() and hasChildren(). Models that are dynamically populated are not as fully tested here. The models rowCount() is tested more extensively in _check_children(), but this catches the big mistakes. """ # check top row top_index = self._model.index(0, 0, QtCore.QModelIndex()) rows = self._model.rowCount(top_index) assert rows >= 0 columns = self._column_count(top_index) assert columns >= 0 if rows == 0 or columns == 0: return assert self._has_children(top_index) second_level_index = self._model.index(0, 0, top_index) assert second_level_index.isValid() rows = self._model.rowCount(second_level_index) assert rows >= 0 columns = self._column_count(second_level_index) assert columns >= 0 if rows == 0 or columns == 0: return assert self._has_children(second_level_index)
def create_char( cls, char: str, size: int, background: types.ColorType = "black", color: types.ColorType = "white", ): pixmap = cls(size, size) pixmap.fill(QtCore.Qt.transparent) with gui.Painter(pixmap) as painter: painter.setRenderHints(painter.Antialiasing | painter.TextAntialiasing | painter.SmoothPixmapTransform) bg_color = colors.get_color(background) painter.setPen(bg_color) painter.setBrush(bg_color) margin = 1 + size // 16 text_margin = size // 20 rect = QtCore.QRectF(margin, margin, size - 2 * margin, size - 2 * margin) painter.drawRoundedRect(rect, 30.0, 30.0, QtCore.Qt.RelativeSize) painter.setPen(colors.get_color(color)) font = painter.font() # type: QtGui.QFont font.setPixelSize(size - 2 * margin - 2 * text_margin) painter.setFont(font) painter.drawText(rect, QtCore.Qt.AlignCenter, char) return pixmap
def index_of(self, url: types.UrlType) -> QtCore.QModelIndex | None: if isinstance(url, str): url = QtCore.QUrl(url) idx = self.indexOf(url) if not idx.isValid(): return None return idx
def _parent(self, index: QtCore.QModelIndex): """Test parent.""" model_types = (QtCore.QAbstractListModel, QtCore.QAbstractTableModel) if isinstance(self._model, model_types): return QtCore.QModelIndex() else: return self._model.parent(index)
def write_bytearray(cls, ba: types.ByteArrayType, write_to: types.QtSerializableType): if isinstance(ba, str): ba = ba.encode() if not isinstance(ba, QtCore.QByteArray): ba = QtCore.QByteArray(ba) stream = cls(ba, core.iodevice.OPEN_MODES["read_only"]) stream >> write_to
def from_file(cls, path: types.PathType) -> Pixmap: path = pathlib.Path(path) with path.open(mode="rb") as f: data = f.read() # Create widget pixmap = cls() pixmap.loadFromData(QtCore.QByteArray(data)) return pixmap
def get_image_formats_for_mime_type(typ: types.ByteArrayType) -> list[str]: if isinstance(typ, str): typ = typ.encode() if isinstance(typ, bytes): typ = QtCore.QByteArray(typ) return [ bytes(i).decode() for i in ImageReader.imageFormatsForMimeType(typ) ]
def append_rows(self, num_rows: int, parent: QtCore.QModelIndex | None = None): parent = QtCore.QModelIndex() if parent is None else parent self.beginInsertRows(parent, self.rowCount(), self.rowCount() + num_rows - 1) yield None self.endInsertRows()
def test_painterpath(): path = gui.PainterPath() rect = core.RectF(0, 0, 1, 1) path.addRect(rect) assert len(path) == 5 assert bool(path) assert core.PointF(0.5, 0.5) in path path[1] = (0.5, 0.5) path.add_rect(QtCore.QRect(0, 0, 1, 1))
def test_barcategoryaxis(qtbot): obj = QtCore.QObject() axis = charts.BarCategoryAxis(obj) axis += "a" axis += "b" assert axis[0] == "a" axis["a"] = "c" assert list(axis) == ["c", "b"] del axis["b"]
def add_mapping(self, widget: QtWidgets.QWidget, section: int, property_name: str | None = None): if property_name is None: self.addMapping(widget, section) else: ba = QtCore.QByteArray(property_name.encode()) self.addMapping(widget, section, ba)
def add_property_animation( self, obj: QtCore.QObject, attribute: types.ByteArrayType) -> core.PropertyAnimation: if isinstance(attribute, str): attribute = attribute.encode() if isinstance(attribute, bytes): attribute = QtCore.QByteArray(attribute) anim = core.PropertyAnimation(obj, attribute) self.addAnimation(anim) return anim
def test_nmeapositioninfosource(): obj = QtCore.QObject() source = positioning.NmeaPositionInfoSource("real_time", obj) print(repr(source)) assert source.get_update_mode() == "real_time" assert source.get_error() == "unknown_source" source.set_preferred_positioning_methods("satellite") assert source.get_preferred_positioning_methods() == ["satellite", "all"] with pytest.raises(InvalidParamError): source.set_preferred_positioning_methods("test") source.get_supported_positioning_methods()
def test_clipboard(qapp): cb = qapp.get_clipboard() mimedata = QtCore.QMimeData() pixmap = gui.Pixmap(100, 100) image = pixmap.toImage() cb.set_mimedata(mimedata) cb.set_image(image) cb.set_pixmap(pixmap) assert cb.get_mimedata() assert cb.get_image() == image assert cb.get_pixmap().size() == pixmap.size()
def window_frame_section_at( self, point: types.PointType) -> constants.WindowFrameSectionStr: """Return the window frame section at given position. Returns: str: Window frame section """ if isinstance(point, tuple): point = QtCore.QPoint(*point) return constants.WINDOW_FRAME_SECTION.inverse[ self.windowFrameSectionAt(point)]
def _test_parent(self): """Test model's implementation of QAbstractItemModel::parent().""" # Make sure the model won't crash and will return an invalid # QModelIndex when asked for the parent of an invalid index. assert not self._parent(QtCore.QModelIndex()).isValid() if not self._has_children(): return # Column 0 | Column 1 | # QModelIndex() | | # \- top_index | top_index_1 | # \- child_index | child_index_1 | # Common error test #1, make sure that a top level index has a parent # that is a invalid QModelIndex. top_index = self._model.index(0, 0, QtCore.QModelIndex()) assert not self._parent(top_index).isValid() # Common error test #2, make sure that a second level index has a # parent that is the first level index. if self._has_children(top_index): child_index = self._model.index(0, 0, top_index) assert self._parent(child_index) == top_index # Common error test #3, the second column should NOT have the same # children as the first column in a row. # Usually the second column shouldn't have children. if self._model.hasIndex(0, 1): top_index_1 = self._model.index(0, 1, QtCore.QModelIndex()) if self._has_children(top_index) and self._has_children( top_index_1): child_index = self._model.index(0, 0, top_index) assert child_index.isValid() child_index_1 = self._model.index(0, 0, top_index_1) assert child_index_1.isValid() assert child_index != child_index_1 # Full test, walk n levels deep through the model making sure that all # parent's children correctly specify their parent. self._check_children(QtCore.QModelIndex())
def remove_rows( self, first: int | None = None, last: int | None = None, parent: QtCore.QModelIndex | None = None, ): parent = QtCore.QModelIndex() if parent is None else parent first = first if first is not None else 0 last = last if last is not None else self.rowCount() self.beginRemoveRows(parent, first, last) yield None self.endRemoveRows()
def show_text( cls, position: types.PointType | None = None, text: str = "", linebreak_px: int = 400, ): if position is None: position = QtGui.QCursor.pos() elif isinstance(position, tuple): position = QtCore.QPoint(*position) cls.showText(position, f'<div style="max-width: {linebreak_px}px">{text}</div>')