diff --git a/README.md b/README.md index a93ce1d..fc2005a 100644 --- a/README.md +++ b/README.md @@ -19,25 +19,31 @@ Components are tested on: - PyQt5 (5.11 and above) & PyQt6 - PySide2 (5.11 and above) & PySide6 +## Documentation + +Documentation is available at https://napari.org/superqt + ## Widgets -Widgets include: +superqt provides a variety of widgets that are not included in the native QtWidgets module, including multihandle (range) sliders, comboboxes, and more. -- [Float Slider](docs/sliders.md#float-slider) +See the [widgets documentation](https://napari.org/superqt/widgets) for a full list of widgets. - [Range Slider](docs/sliders.md#range-slider) (multi-handle slider) range sliders -- [Labeled Sliders](docs/sliders.md#labeled-sliders) (sliders with linked - spinboxes) - range sliders range sliders -- Unbound Integer SpinBox (backed by python `int`) +## Utilities + +superqt includes a number of utitlities for working with Qt, including: + +- tools and decorators for working with threads in qt. +- `superqt.fonticon` for generating icons from font files (such as [Material Design Icons](https://materialdesignicons.com/) and [Font Awesome](https://fontawesome.com/)) ## Contributing diff --git a/docs/utilities/fonticon.md b/docs/utilities/fonticon.md new file mode 100644 index 0000000..aeb0ec1 --- /dev/null +++ b/docs/utilities/fonticon.md @@ -0,0 +1,101 @@ +# Font icons + +The `superqt.fonticon` module provides a set of utilities for working with font +icons such as [Font Awesome](https://fontawesome.com/) or [Material Design +Icons](https://materialdesignicons.com/). + +## Basic Example + +```python +from fonticon_fa5 import FA5S + +from qtpy.QtCore import QSize +from qtpy.QtWidgets import QApplication, QPushButton + +from superqt.fonticon import icon, pulse + +app = QApplication([]) + +btn2 = QPushButton() +btn2.setIcon(icon(FA5S.smile, color="blue")) +btn2.setIconSize(QSize(225, 225)) +btn2.show() + +app.exec() +``` + +{{ show_widget(225) }} + +## Font Icon plugins + +Ready-made fonticon packs are available as plugins: + +### [Font Awesome 5](https://fontawesome.com/v5/search) + +```bash +pip install fonticon-fontawesome5 +``` + +### [Font Awesome 6](https://fontawesome.com/v6/search) + +```bash +pip install fonticon-fontawesome6 +``` + +### [Material Design Icons](https://materialdesignicons.com/) + +```bash +pip install fonticon-materialdesignicons6 +``` + +### See also + +- +- +- + +`superqt.fonticon` is a pluggable system, and font icon packs may use the `"superqt.fonticon"` +entry point to register themselves with superqt. See [`fonticon-cookiecutter`](https://github.com/tlambert03/fonticon-cookiecutter) for a template, or look through the following repos for examples: + +- +- +- + +## API + +::: superqt.fonticon.icon + options: + heading_level: 3 + +::: superqt.fonticon.setTextIcon + options: + heading_level: 3 + +::: superqt.fonticon.font + options: + heading_level: 3 + +::: superqt.fonticon.IconOpts + options: + heading_level: 3 + +::: superqt.fonticon.addFont + options: + heading_level: 3 + +## Animations + +the `animation` parameter to `icon()` accepts a subclass of +`Animation` that will be + +::: superqt.fonticon.Animation + options: + heading_level: 3 + +::: superqt.fonticon.pulse + options: + heading_level: 3 + +::: superqt.fonticon.spin + options: + heading_level: 3 diff --git a/docs/utilities/index.md b/docs/utilities/index.md index e1c2123..dbe6c35 100644 --- a/docs/utilities/index.md +++ b/docs/utilities/index.md @@ -1,8 +1,31 @@ # Utilities +## Font Icons + +| Object | Description | +| ----------- | --------------------- | +| [`addFont`](./fonticon.md#superqt.fonticon.addFont) | Add an `OTF/TTF` file at to the font registry. | +| [`font`](./fonticon.md#superqt.fonticon.font) | Create `QFont` for a given font-icon font family key | +| [`icon`](./fonticon.md#superqt.fonticon.icon) | Create a `QIcon` for font-con glyph key | +| [`setTextIcon`](./fonticon.md#superqt.fonticon.setTextIcon) | Set text on a `QWidget` to a specific font & glyph. | +| [`IconFont`](./fonticon.md#superqt.fonticon.IconFont) | Helper class that provides a standard way to create an `IconFont`. | +| [`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. | + +## Threading tools + +| Object | Description | +| ----------- | --------------------- | +| [`ensure_main_thread`](./thread_decorators.md#ensure_main_thread) | Decorator that ensures a function is called in the main `QApplication` thread. | +| [`ensure_object_thread`](./thread_decorators.md#ensure_object_thread) | Decorator that ensures a `QObject` method is called in the object's thread. | +| [`FunctionWorker`](./threading.md#superqt.utils.FunctionWorker) | `QRunnable` with signals that wraps a simple long-running function. | +| [`GeneratorWorker`](./threading.md#superqt.utils.GeneratorWorker) | `QRunnable` with signals that wraps a long-running generator. | +| [`create_worker`](./threading.md#superqt.utils.create_worker) | Create a worker to run a target function in another thread. | +| [`thread_worker`](./threading.md#superqt.utils.thread_worker) | Decorator for `create_worker`, turn a function into a worker. | + +## Miscellaneous + | Object | Description | | ----------- | --------------------- | | [`QMessageHandler`](./qmessagehandler.md) | A context manager to intercept messages from Qt. | -| [`ensure_main_thread`](./thread_decorators.md#ensure_main_thread) | Decorator that ensures a function is called in the main `QApplication` thread. | -| [`ensure_object_thread`](./thread_decorators.md#ensure_object_thread) | Decorator that ensures a `QObject` method is called in the object's thread. | | [`CodeSyntaxHighlight`](./code_syntax_highlight.md) | A `QSyntaxHighlighter` for code syntax highlighting. | diff --git a/src/superqt/fonticon/__init__.py b/src/superqt/fonticon/__init__.py index 7b4538c..6062ab0 100644 --- a/src/superqt/fonticon/__init__.py +++ b/src/superqt/fonticon/__init__.py @@ -2,14 +2,15 @@ from __future__ import annotations __all__ = [ "addFont", + "Animation", "ENTRY_POINT", "font", "icon", "IconFont", "IconFontMeta", "IconOpts", - "Animation", "pulse", + "setTextIcon", "spin", ] @@ -49,10 +50,11 @@ def icon( The `glyph_key` (e.g. 'fa5s.smile') represents a Font-family & style, and a glpyh. In most cases, the key should be provided by a plugin in the environment, like: - https://github.com/tlambert03/fonticon-fontawesome5 ('fa5s' & 'fa5r' prefixes) - https://github.com/tlambert03/fonticon-materialdesignicons6 ('mdi6' prefix) - ...but fonts can also be added manually using :func:`addFont`. + - [fonticon-fontawesome5](https://pypi.org/project/fonticon-fontawesome5/) ('fa5s' & 'fa5r' prefixes) + - [fonticon-materialdesignicons6](https://pypi.org/project/fonticon-materialdesignicons6/) ('mdi6' prefix) + + ...but fonts can also be added manually using [`addFont`][superqt.fonticon.addFont]. Parameters ---------- @@ -96,19 +98,22 @@ def icon( Examples -------- - # simple example (assumes the font-awesome5 plugin is installed) + + simple example (using the string `'fa5s.smile'` assumes the `fonticon-fontawesome5` + plugin is installed) + >>> btn = QPushButton() >>> btn.setIcon(icon('fa5s.smile')) - # can also directly import from fonticon_fa5 + can also directly import from fonticon_fa5 >>> from fonticon_fa5 import FA5S >>> btn.setIcon(icon(FA5S.smile)) - # with animation + with animation >>> btn2 = QPushButton() >>> btn2.setIcon(icon(FA5S.spinner, animation=pulse(btn2))) - # complicated example + complicated example >>> btn = QPushButton() >>> btn.setIcon( ... icon( @@ -152,7 +157,7 @@ def setTextIcon(widget: QWidget, glyph_key: str, size: Optional[float] = None) - Parameters ---------- - wdg : QWidget + widget : QWidget A widget supporting a `setText` method. glyph_key : str String encapsulating a font-family, style, and glyph. e.g. 'fa5s.smile'. @@ -190,10 +195,12 @@ def addFont( to their unicode numbers. If a charmap is not provided, glyphs must be directly accessed with their unicode as something like `key.\uffff`. - NOTE: in most cases, users will not need this. - Instead, they should install a font plugin, like: - https://github.com/tlambert03/fonticon-fontawesome5 - https://github.com/tlambert03/fonticon-materialdesignicons6 + !!! Note + in most cases, users will not need this. Instead, they should install a + font plugin, like: + + - [fonticon-fontawesome5](https://pypi.org/project/fonticon-fontawesome5/) + - [fonticon-materialdesignicons6](https://pypi.org/project/fonticon-materialdesignicons6/) Parameters ---------- diff --git a/src/superqt/fonticon/_animations.py b/src/superqt/fonticon/_animations.py index c86bab3..e01c4ab 100644 --- a/src/superqt/fonticon/_animations.py +++ b/src/superqt/fonticon/_animations.py @@ -6,6 +6,8 @@ from qtpy.QtWidgets import QWidget class Animation(ABC): + """Base icon animation class.""" + def __init__(self, parent_widget: QWidget, interval: int = 10, step: int = 1): self.parent_widget = parent_widget self.timer = QTimer() @@ -25,6 +27,8 @@ class Animation(ABC): class spin(Animation): + """Animation that smoothly spins an icon.""" + def animate(self, painter: QPainter): if not self.timer.isActive(): self.timer.start() @@ -36,5 +40,7 @@ class spin(Animation): class pulse(spin): + """Animation that spins an icon in slower, discrete steps.""" + def __init__(self, parent_widget: QWidget = None): super().__init__(parent_widget, interval=200, step=45) diff --git a/src/superqt/fonticon/_qfont_icon.py b/src/superqt/fonticon/_qfont_icon.py index 60f2109..4491660 100644 --- a/src/superqt/fonticon/_qfont_icon.py +++ b/src/superqt/fonticon/_qfont_icon.py @@ -102,6 +102,23 @@ class IconOptionDict(TypedDict, total=False): # IconOptions are. @dataclass class IconOpts: + """Options for rendering an icon. + + Parameters + ---------- + glyph_key : str, optional + The key of the glyph to use, e.g. `'fa5s.smile'`, by default `None` + scale_factor : float, optional + The scale factor to use, by default `None` + color : ValidColor, optional + The color to use, by default `None`. Colors may be specified as a string, + `QColor`, `Qt.GlobalColor`, or a 3 or 4-tuple of integers. + opacity : float, optional + The opacity to use, by default `None` + animation : Animation, optional + The animation to use, by default `None` + """ + glyph_key: Union[str, Unset] = _Unset scale_factor: Union[float, Unset] = _Unset color: Union[ValidColor, Unset] = _Unset @@ -418,7 +435,7 @@ class QFontIconStore(QObject): If you'd like to later use a fontkey in the form of `key.some-name`, then `charmap` must be provided and provide a mapping for all of the glyph names to their unicode numbers. If a charmap is not provided, glyphs must be directly - accessed with their unicode as something like `key.\uffff`. + accessed with their unicode as something like `key.\\uffff`. Parameters ---------- @@ -509,7 +526,7 @@ class QFontIconStore(QObject): ) -> None: """Sets text on a widget to a specific font & glyph. - This is an alternative to setting a QIcon with a pixmap. It may + This is an alternative to setting a `QIcon` with a pixmap. It may be easier to combine with dynamic stylesheets. """ setText = getattr(widget, "setText", None)