mirror of
https://github.com/pyapp-kit/superqt.git
synced 2025-08-12 05:21:34 +02:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f9bc334228 | ||
|
55732afa71 | ||
|
22372f58a4 | ||
|
e990284bd1 | ||
|
7850e53b61 | ||
|
68bafaceaa | ||
|
0b1cd1b11a | ||
|
646cb4ea48 |
@@ -5,7 +5,7 @@ ci:
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.8.1
|
||||
rev: v0.9.9
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix, --unsafe-fixes]
|
||||
@@ -17,7 +17,7 @@ repos:
|
||||
- id: validate-pyproject
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.13.0
|
||||
rev: v1.15.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
exclude: tests|examples
|
||||
|
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,5 +1,21 @@
|
||||
# Changelog
|
||||
|
||||
## [v0.7.2](https://github.com/pyapp-kit/superqt/tree/v0.7.2) (2025-03-17)
|
||||
|
||||
[Full Changelog](https://github.com/pyapp-kit/superqt/compare/v0.7.1...v0.7.2)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- fix: less Slider signal renaming, make alternate signal types public [\#283](https://github.com/pyapp-kit/superqt/pull/283) ([tlambert03](https://github.com/tlambert03))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- ci: \[pre-commit.ci\] autoupdate [\#282](https://github.com/pyapp-kit/superqt/pull/282) ([pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci))
|
||||
- ci: \[pre-commit.ci\] autoupdate [\#279](https://github.com/pyapp-kit/superqt/pull/279) ([pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci))
|
||||
- Update CONTRIBUTING.md to include \[test\] and mention Qt backend [\#276](https://github.com/pyapp-kit/superqt/pull/276) ([psobolewskiPhD](https://github.com/psobolewskiPhD))
|
||||
- Update CONTRIBUTING.md to install .\[dev\] first then pre-commit [\#275](https://github.com/pyapp-kit/superqt/pull/275) ([psobolewskiPhD](https://github.com/psobolewskiPhD))
|
||||
- ci: \[pre-commit.ci\] autoupdate [\#272](https://github.com/pyapp-kit/superqt/pull/272) ([pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci))
|
||||
|
||||
## [v0.7.1](https://github.com/pyapp-kit/superqt/tree/v0.7.1) (2025-01-05)
|
||||
|
||||
[Full Changelog](https://github.com/pyapp-kit/superqt/compare/v0.7.0...v0.7.1)
|
||||
|
@@ -12,12 +12,12 @@ To get started fork this repository, and clone your fork:
|
||||
git clone https://github.com/<your_organization>/superqt
|
||||
cd superqt
|
||||
|
||||
# install in editable mode (this will install PyQt6 as the Qt backend)
|
||||
pip install -e .[dev]
|
||||
|
||||
# install pre-commit hooks
|
||||
pre-commit install
|
||||
|
||||
# install in editable mode
|
||||
pip install -e .[dev]
|
||||
|
||||
# run tests & make sure everything is working!
|
||||
pytest
|
||||
```
|
||||
|
36
docs/utilities/iconify.md
Normal file
36
docs/utilities/iconify.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# QIconifyIcon
|
||||
|
||||
[Iconify](https://iconify.design/) is an icon library that includes 150,000+
|
||||
icons from most major icon sets including Bootstrap, FontAwesome, Material
|
||||
Design, and many more; each available as individual SVGs. Unlike the
|
||||
[`superqt.fonticon` module](./fonticon.md), `superqt.QIconifyIcon` does not require any additional
|
||||
dependencies or font files to be installed. Icons are downloaded (and cached)
|
||||
on-demand from the Iconify API, using [pyconify](https://github.com/pyapp-kit/pyconify)
|
||||
|
||||
Search availble icons at <https://icon-sets.iconify.design>
|
||||
Once you find one you like, use the key in the format `"prefix:name"` to create an
|
||||
icon: `QIconifyIcon("bi:bell")`.
|
||||
|
||||
## Basic Example
|
||||
|
||||
```python
|
||||
from qtpy.QtCore import QSize
|
||||
from qtpy.QtWidgets import QApplication, QPushButton
|
||||
|
||||
from superqt import QIconifyIcon
|
||||
|
||||
app = QApplication([])
|
||||
|
||||
btn = QPushButton()
|
||||
btn.setIcon(QIconifyIcon("fluent-emoji-flat:alarm-clock"))
|
||||
btn.setIconSize(QSize(60, 60))
|
||||
btn.show()
|
||||
|
||||
app.exec()
|
||||
```
|
||||
|
||||
{{ show_widget(225) }}
|
||||
|
||||
::: superqt.QIconifyIcon
|
||||
options:
|
||||
heading_level: 3
|
@@ -12,6 +12,12 @@
|
||||
| [`IconOpts`](./fonticon.md#superqt.fonticon.IconOpts) | Options for rendering an icon |
|
||||
| [`Animation`](./fonticon.md#superqt.fonticon.Animation) | Base class for adding animations to a font-icon. |
|
||||
|
||||
## SVG Icons
|
||||
|
||||
| Object | Description |
|
||||
| ----------- | --------------------- |
|
||||
| [`QIconifyIcon`](./iconify.md) | QIcons backed by the [Iconify](https://iconify.design/) icon library. |
|
||||
|
||||
## Threading tools
|
||||
|
||||
| Object | Description |
|
||||
|
@@ -32,8 +32,8 @@ markdown_extensions:
|
||||
- attr_list
|
||||
- md_in_html
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
- toc:
|
||||
permalink: "#"
|
||||
|
||||
|
@@ -65,13 +65,14 @@ dev = [
|
||||
"pydocstyle",
|
||||
"rich",
|
||||
"types-Pygments",
|
||||
"superqt[test,pyqt6]",
|
||||
]
|
||||
docs = [
|
||||
"mkdocs-macros-plugin",
|
||||
"mkdocs-material",
|
||||
"mkdocstrings[python]",
|
||||
"pint",
|
||||
"cmap",
|
||||
"mkdocs-macros-plugin ==1.3.7",
|
||||
"mkdocs-material ==9.5.49",
|
||||
"mkdocstrings ==0.27.0",
|
||||
"mkdocstrings-python ==1.13.0",
|
||||
"superqt[font-fa5, cmap, quantity]",
|
||||
]
|
||||
quantity = ["pint"]
|
||||
cmap = ["cmap >=0.1.1"]
|
||||
|
@@ -56,9 +56,9 @@ __all__ = [
|
||||
]
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .combobox import QColormapComboBox # noqa: TC004
|
||||
from .iconify import QIconifyIcon # noqa: TC004
|
||||
from .spinbox._quantity import QQuantity # noqa: TC004
|
||||
from .combobox import QColormapComboBox
|
||||
from .iconify import QIconifyIcon
|
||||
from .spinbox._quantity import QQuantity
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
|
@@ -13,7 +13,7 @@ __all__ = (
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from superqt.cmap import QColormapComboBox # noqa: TC004
|
||||
from superqt.cmap import QColormapComboBox
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any: # pragma: no cover
|
||||
|
@@ -29,19 +29,21 @@ class _GenericRangeSlider(_GenericSlider):
|
||||
"""
|
||||
|
||||
# Emitted when the slider value has changed, with the new slider values
|
||||
_valuesChanged = Signal(tuple)
|
||||
valuesChanged = Signal(tuple)
|
||||
# this is just a hack to allow napari v0.4.19 tests to pass)
|
||||
# since it used the presence of this private signal as a duck-typing check.
|
||||
_valuesChanged = valuesChanged
|
||||
|
||||
# Emitted when sliderDown is true and the slider moves
|
||||
# This usually happens when the user is dragging the slider
|
||||
# The value is the positions of *all* handles.
|
||||
_slidersMoved = Signal(tuple)
|
||||
slidersMoved = Signal(tuple)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._style = RangeSliderStyle()
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
self.valueChanged = self._valuesChanged
|
||||
self.sliderMoved = self._slidersMoved
|
||||
|
||||
# list of values
|
||||
self._value: list[_T] = [20, 80]
|
||||
|
||||
@@ -64,6 +66,10 @@ class _GenericRangeSlider(_GenericSlider):
|
||||
|
||||
self.setStyleSheet("")
|
||||
|
||||
def _rename_signals(self) -> None:
|
||||
self.valueChanged = self.valuesChanged
|
||||
self.sliderMoved = self.slidersMoved
|
||||
|
||||
# ############### New Public API #######################
|
||||
|
||||
def barIsRigid(self) -> bool:
|
||||
|
@@ -22,7 +22,7 @@ QRangeSlider.
|
||||
|
||||
import os
|
||||
import platform
|
||||
from typing import TypeVar
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from qtpy import QT_VERSION, QtGui
|
||||
from qtpy.QtCore import QEvent, QPoint, QPointF, QRect, Qt, Signal
|
||||
@@ -60,13 +60,13 @@ USE_MAC_SLIDER_PATCH = (
|
||||
|
||||
|
||||
class _GenericSlider(QSlider):
|
||||
_fvalueChanged = Signal(int)
|
||||
_fsliderMoved = Signal(int)
|
||||
_frangeChanged = Signal(int, int)
|
||||
fvalueChanged = Signal(float)
|
||||
fsliderMoved = Signal(float)
|
||||
frangeChanged = Signal(float, float)
|
||||
|
||||
MAX_DISPLAY = 5000
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
self._minimum = 0.0
|
||||
self._maximum = 99.0
|
||||
self._pageStep = 10.0
|
||||
@@ -90,15 +90,18 @@ class _GenericSlider(QSlider):
|
||||
self._control_fraction = 0.04
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
self.valueChanged = self._fvalueChanged
|
||||
self.sliderMoved = self._fsliderMoved
|
||||
self.rangeChanged = self._frangeChanged
|
||||
self._rename_signals()
|
||||
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_Hover)
|
||||
self.setStyleSheet("")
|
||||
if USE_MAC_SLIDER_PATCH:
|
||||
self.applyMacStylePatch()
|
||||
|
||||
def _rename_signals(self) -> None:
|
||||
self.valueChanged = self.fvalueChanged
|
||||
self.sliderMoved = self.fsliderMoved
|
||||
self.rangeChanged = self.frangeChanged
|
||||
|
||||
def applyMacStylePatch(self) -> None:
|
||||
"""Apply a QSS patch to fix sliders on macos>=12 with QT < 6.
|
||||
|
||||
|
@@ -162,9 +162,6 @@ def _handle_overloaded_slider_sig(
|
||||
|
||||
class QLabeledSlider(_SliderProxy, QAbstractSlider):
|
||||
editingFinished = Signal()
|
||||
_ivalueChanged = Signal(int)
|
||||
_isliderMoved = Signal(int)
|
||||
_irangeChanged = Signal(int, int)
|
||||
|
||||
_slider_class = QSlider
|
||||
_slider: QSlider
|
||||
@@ -283,18 +280,15 @@ class QLabeledSlider(_SliderProxy, QAbstractSlider):
|
||||
"""Convert the value from float to int before setting the slider value."""
|
||||
self._slider.setValue(int(value))
|
||||
|
||||
def _rename_signals(self) -> None:
|
||||
self.valueChanged = self._ivalueChanged
|
||||
self.sliderMoved = self._isliderMoved
|
||||
self.rangeChanged = self._irangeChanged
|
||||
def _rename_signals(self) -> None: ...
|
||||
|
||||
|
||||
class QLabeledDoubleSlider(QLabeledSlider):
|
||||
_slider_class = QDoubleSlider
|
||||
_slider: QDoubleSlider
|
||||
_fvalueChanged = Signal(float)
|
||||
_fsliderMoved = Signal(float)
|
||||
_frangeChanged = Signal(float, float)
|
||||
fvalueChanged = Signal(float)
|
||||
fsliderMoved = Signal(float)
|
||||
frangeChanged = Signal(float, float)
|
||||
|
||||
@overload
|
||||
def __init__(self, parent: QWidget | None = ...) -> None: ...
|
||||
@@ -313,9 +307,9 @@ class QLabeledDoubleSlider(QLabeledSlider):
|
||||
self._slider.setValue(value)
|
||||
|
||||
def _rename_signals(self) -> None:
|
||||
self.valueChanged = self._fvalueChanged
|
||||
self.sliderMoved = self._fsliderMoved
|
||||
self.rangeChanged = self._frangeChanged
|
||||
self.valueChanged = self.fvalueChanged
|
||||
self.sliderMoved = self.fsliderMoved
|
||||
self.rangeChanged = self.frangeChanged
|
||||
|
||||
def decimals(self) -> int:
|
||||
return self._label.decimals()
|
||||
@@ -325,9 +319,7 @@ class QLabeledDoubleSlider(QLabeledSlider):
|
||||
|
||||
|
||||
class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
|
||||
_valueChanged = Signal(tuple)
|
||||
_sliderPressed = Signal()
|
||||
_sliderReleased = Signal()
|
||||
valuesChanged = Signal(tuple)
|
||||
editingFinished = Signal()
|
||||
|
||||
_slider_class = QRangeSlider
|
||||
@@ -359,7 +351,7 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
|
||||
self._slider.sliderPressed.connect(self.sliderPressed.emit)
|
||||
self._slider.sliderReleased.connect(self.sliderReleased.emit)
|
||||
self._slider.rangeChanged.connect(self.rangeChanged.emit)
|
||||
self.sliderMoved = self._slider._slidersMoved
|
||||
self.sliderMoved = self._slider.slidersMoved
|
||||
|
||||
self._min_label = SliderLabel(
|
||||
self._slider,
|
||||
@@ -492,9 +484,7 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
|
||||
|
||||
# ------------- private methods ----------------
|
||||
def _rename_signals(self) -> None:
|
||||
self.valueChanged = self._valueChanged
|
||||
self.sliderReleased = self._sliderReleased
|
||||
self.sliderPressed = self._sliderPressed
|
||||
self.valueChanged = self.valuesChanged
|
||||
|
||||
def _reposition_labels(self) -> None:
|
||||
if (
|
||||
@@ -602,7 +592,7 @@ class QLabeledRangeSlider(_SliderProxy, QAbstractSlider):
|
||||
class QLabeledDoubleRangeSlider(QLabeledRangeSlider):
|
||||
_slider_class = QDoubleRangeSlider
|
||||
_slider: QDoubleRangeSlider
|
||||
_frangeChanged = Signal(float, float)
|
||||
frangeChanged = Signal(float, float)
|
||||
|
||||
@overload
|
||||
def __init__(self, parent: QWidget | None = ...) -> None: ...
|
||||
@@ -618,7 +608,7 @@ class QLabeledDoubleRangeSlider(QLabeledRangeSlider):
|
||||
|
||||
def _rename_signals(self) -> None:
|
||||
super()._rename_signals()
|
||||
self.rangeChanged = self._frangeChanged
|
||||
self.rangeChanged = self.frangeChanged
|
||||
|
||||
def decimals(self) -> int:
|
||||
return self._min_label.decimals()
|
||||
|
@@ -14,10 +14,6 @@ class _IntMixin:
|
||||
|
||||
|
||||
class _FloatMixin:
|
||||
_fvalueChanged = Signal(float)
|
||||
_fsliderMoved = Signal(float)
|
||||
_frangeChanged = Signal(float, float)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._singleStep = 0.01
|
||||
@@ -41,7 +37,9 @@ class QRangeSlider(_IntMixin, _GenericRangeSlider):
|
||||
|
||||
|
||||
class QDoubleRangeSlider(_FloatMixin, QRangeSlider):
|
||||
pass
|
||||
def _rename_signals(self) -> None:
|
||||
super()._rename_signals()
|
||||
self.rangeChanged = self.frangeChanged
|
||||
|
||||
|
||||
# QRangeSlider.__doc__ += "\n" + textwrap.indent(QSlider.__doc__, " ")
|
||||
|
@@ -1,7 +1,7 @@
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from superqt.cmap import draw_colormap # noqa: TC004
|
||||
from superqt.cmap import draw_colormap
|
||||
|
||||
__all__ = (
|
||||
"CodeSyntaxHighlight",
|
||||
|
Reference in New Issue
Block a user