Skip to content

Commit

Permalink
Merge pull request #69 from wojtryb/development
Browse files Browse the repository at this point in the history
Deploy 1.4.1
  • Loading branch information
wojtryb authored Oct 20, 2023
2 parents 9695bed + 3bb0361 commit 48d965a
Show file tree
Hide file tree
Showing 42 changed files with 110 additions and 101 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Shortcut composer **v1.4.0**
# Shortcut composer **v1.4.1**

[![python](https://img.shields.io/badge/Python-3.8-3776AB.svg?style=flat&logo=python&logoColor=white)](https://www.python.org)
[![Code style: black](https://img.shields.io/badge/code%20style-autopep8-333333.svg)](https://pypi.org/project/autopep8/)
Expand Down Expand Up @@ -39,7 +39,7 @@ The plugin adds new shortcuts of the following types:
[![PIE MENUS - release video](https://github-production-user-asset-6210df.s3.amazonaws.com/51094047/238179887-87c00d86-0e65-46c2-94c4-52bb02c99501.png)](https://youtu.be/hrjBycVYFZM "PIE MENUS - introducing Shortcut Composer")

## Requirements
- Version of krita on plugin release: **5.1.5**
- Version of krita on plugin release: **5.2.0**
- Required version of krita: **5.1.0** or later

OS support state:
Expand All @@ -49,7 +49,7 @@ OS support state:
- [ ] Android (Does not support python plugins yet)

> **Note**
> On **Linux** the only oficially supported version of Krita is **.appimage**, which ships with all required dependencies. Running the plugin on Krita installed from Snap or distribution repositories is not recommended as it may not work out of the box and may require extra dependency-related work.
> On **Linux** the only officially supported version of Krita is **.appimage**, which ships with all required dependencies. Running the plugin on Krita installed from Snap or distribution repositories is not recommended as it may not work out of the box and may require extra dependency-related work.
## How to install or update the plugin:
Installation steps are THE SAME for installing the plugin for the first time and for updating it to the new version:
Expand All @@ -62,7 +62,7 @@ Installation steps are THE SAME for installing the plugin for the first time and
4. Set custom shortcuts in **Settings > Configure Krita > Keyboard Shortcuts** under **Scripts > Shortcut Composer: ...** sections. By intention, there are no default bindings.

> **Warning**
> Some keyboard buttons like **Space, R, Y, V, 1, 2, 3, 4, 5, 6** are reserved for Krita's Canvas Inputs. Assigning those keys to actions (including those from the plugin) may result in conflicts and abnormal behaviour different for each OS. Either avoid those keys, or remove their bindings in **Settings > Configure Krita > Canvas Input Settings**.
> Some keyboard buttons like **Space, R, Y, V, 1, 2, 3, 4, 5, 6** are reserved for Krita's Canvas Inputs. Assigning those keys to actions (including those from the plugin) may result in conflicts and abnormal behavior different for each OS. Either avoid those keys, or remove their bindings in **Settings > Configure Krita > Canvas Input Settings**.

## For krita plugin programmers
Expand Down
2 changes: 1 addition & 1 deletion shortcut_composer.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ X-KDE-Library=shortcut_composer
X-Python-2-Compatible=false
X-Krita-Manual=manual.html
Name=Shortcut Composer
Comment=Api for creating complex krita keyboard shortcuts.
Comment=Plugin for creating complex krita keyboard shortcuts.
2 changes: 1 addition & 1 deletion shortcut_composer/INFO.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-FileCopyrightText: © 2022-2023 Wojciech Trybus <[email protected]>
# SPDX-License-Identifier: GPL-3.0-or-later

__version__ = "1.4.0"
__version__ = "1.4.1"
__author__ = "Wojciech Trybus"
__license__ = "GPL-3.0-or-later"
2 changes: 1 addition & 1 deletion shortcut_composer/api_krita/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
### Alternative Krita API
Package `api_krita` wraps krita api offering PEP8 compatibility, typings, and docstring documentation. Most of objects attributes are now available as settables properties.
Package `api_krita` wraps krita api offering PEP8 compatibility, typings, and docstring documentation. Most of objects attributes are now available as settable properties.

```python
from .api_krita import Krita
Expand Down
14 changes: 7 additions & 7 deletions shortcut_composer/api_krita/actions/transform_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class TransformModeFinder:
- Buttons of every transform modes from the tool options widget
- Button used to apply the changes of transform tool
As the widget do not exist during plugin intialization phase,
As the widget do not exist during plugin initialization phase,
fetching the elements needs to happen at runtime. If wrappers get
deleted by C++, the fetching may need to be done again.
"""
Expand Down Expand Up @@ -119,16 +119,16 @@ def get_active_mode(self) -> Optional[TransformMode]:

def _fetch_transform_options(self) -> QWidget:
"""Fetch widget with transform tool options."""
for qobj in Krita.get_active_qwindow().findChildren(QWidget):
if qobj.objectName() == "KisToolTransform option widget":
return qobj # type: ignore
for q_obj in Krita.get_active_qwindow().findChildren(QWidget):
if q_obj.objectName() == "KisToolTransform option widget":
return q_obj # type: ignore
raise RuntimeError("Transform options not found.")

def _fetch_mode_button(self, mode: TransformMode) -> QToolButton:
"""Fetch a button that activates a given mode."""
for qobj in self._transform_options.findChildren(QToolButton):
if qobj.objectName() == mode.button_name:
return qobj # type: ignore
for q_obj in self._transform_options.findChildren(QToolButton):
if q_obj.objectName() == mode.button_name:
return q_obj # type: ignore
raise RuntimeError(f"Could not find the {mode.name} button.")

def _fetch_apply_button(self) -> QPushButton:
Expand Down
4 changes: 2 additions & 2 deletions shortcut_composer/api_krita/core_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ def get_active_canvas(self) -> Canvas:

def get_cursor(self) -> Cursor:
"""Return wrapper of krita `Cursor`. Don't use on plugin init phase."""
qwin = self.get_active_qwindow()
return Cursor(qwin)
q_win = self.get_active_qwindow()
return Cursor(q_win)

def trigger_action(self, action_name: str) -> None:
"""Trigger internal krita action called `action_name`."""
Expand Down
15 changes: 12 additions & 3 deletions shortcut_composer/api_krita/enums/helpers/enum_group.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# SPDX-FileCopyrightText: © 2022-2023 Wojciech Trybus <[email protected]>
# SPDX-License-Identifier: GPL-3.0-or-later

import sys
from typing import Dict, List, Tuple, TypeVar, Optional
from enum import Enum, EnumMeta
T = TypeVar("T", bound=Enum)
Expand Down Expand Up @@ -36,9 +37,17 @@ def __new__(
# Remove groups from attrs, so they won't become Enum members
group_var_names = [k for k, v in items if isinstance(v, Group)]
for group_variable_name in group_var_names:
attrs._member_names.remove(group_variable_name)

# Create Enum class. attrs emtpies itself in a process
members = attrs._member_names
if sys.version_info.major <= 2:
raise RuntimeError("Python 2 not supported")
if sys.version_info.minor <= 10:
# Until 3.10, _EnumDict._member_names was a list
members.remove(group_variable_name)
else:
# From 3.11, _EnumDict._member_names is a dict
del members[group_variable_name]

# Create Enum class. attrs empties itself in a process
new_class = super().__new__(cls, name, bases, attrs)
# List of all groups
group_list = [v for _, v in items if isinstance(v, Group)]
Expand Down
8 changes: 4 additions & 4 deletions shortcut_composer/api_krita/pyqt/pixmap_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ def make_pixmap_round(pixmap: QPixmap) -> QPixmap:
image = pixmap.toImage()
image.convertToFormat(QImage.Format_ARGB32)

imgsize = min(image.width(), image.height())
out_img = QImage(imgsize, imgsize, QImage.Format_ARGB32)
img_size = min(image.width(), image.height())
out_img = QImage(img_size, img_size, QImage.Format_ARGB32)
out_img.fill(Qt.transparent)

painter = QPainter(out_img)
painter.setBrush(QBrush(image))
painter.setPen(Qt.NoPen)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.drawEllipse(0, 0, imgsize, imgsize)
painter.drawEllipse(0, 0, img_size, img_size)
painter.end()

return QPixmap.fromImage(out_img)

@staticmethod
def scale_pixmap(pixmap: QPixmap, size_px: int) -> QPixmap:
"""Scale a square pixmal to new size."""
"""Scale a square pixmap to new size."""
return pixmap.scaled(
size_px,
size_px,
Expand Down
2 changes: 1 addition & 1 deletion shortcut_composer/api_krita/wrappers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
Wrappers of classes in krita API.
Adds typing, dosctrings and changes the interface to be PEP8 compatibile.
Adds typing, docstrings and changes the interface to be PEP8 compatible.
"""

from .tool_descriptor import ToolDescriptor
Expand Down
6 changes: 3 additions & 3 deletions shortcut_composer/api_krita/wrappers/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
class Cursor:
"""Wraps Qt5 cursor for typing, documentation and PEP8 compatibility."""

qwin: QMainWindow
q_win: QMainWindow

def x(self) -> int:
"""Return x axis of cursor in pixels in relation to screen."""
return self.qwin.cursor().pos().x()
return self.q_win.cursor().pos().x()

def y(self) -> int:
"""Return y axis of cursor in pixels in relation to screen."""
return self.qwin.cursor().pos().y()
return self.q_win.cursor().pos().y()
8 changes: 4 additions & 4 deletions shortcut_composer/api_krita/wrappers/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class KritaDocument(Protocol):

def activeNode(self) -> KritaNode: ...
def setActiveNode(self, node: KritaNode): ...
def createNode(self, name: str, node_type: NodeType) -> KritaNode: ...
def createNode(self, name: str, node_type: str) -> KritaNode: ...
def topLevelNodes(self) -> List[KritaNode]: ...
def resolution(self) -> int: ...
def currentTime(self) -> int: ...
Expand Down Expand Up @@ -53,7 +53,7 @@ def create_node(self, name: str, node_type: NodeType) -> Node:
usable from Krita. For example with add_child_node() method of
Node Class.
When relevant, the new Node will have the colorspace of the
When relevant, the new Node will have the color space of the
image by default; that can be changed with Node::setColorSpace.
The settings and selections for relevant layer and mask types
Expand All @@ -69,7 +69,7 @@ def current_time(self) -> int:
@current_time.setter
def current_time(self, time: int) -> None:
"""Set current time using frame number"""
self.document.setCurrentTime(time)
self.document.setCurrentTime(round(time))

def get_top_nodes(self) -> List[Node]:
"""Return a list of `Nodes` without a parent."""
Expand All @@ -86,7 +86,7 @@ def recursive_search(nodes: List[Node], found_so_far: List[Node]):
return recursive_search(self.get_top_nodes(), [])

@property
def dpi(self):
def dpi(self) -> int:
"""Return dpi (dot per inch) of the document."""
return self.document.resolution()

Expand Down
2 changes: 1 addition & 1 deletion shortcut_composer/api_krita/wrappers/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def visible(self, value: bool) -> None:
"""Set visibility of this node."""
self.node.setVisible(value)

def toggle_visility(self) -> None:
def toggle_visibility(self) -> None:
"""Change visibility of this node to the opposite one."""
self.visible = not self.visible

Expand Down
14 changes: 7 additions & 7 deletions shortcut_composer/api_krita/wrappers/tool_descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ def __init__(self) -> None:
def find_active_tool_name(self) -> str:
"""Find and return name of currently active tool."""
self._ensure_toolbox()
for qobj in self.toolbox.findChildren(QToolButton):
if qobj.metaObject().className() == "KoToolBoxButton":
if qobj.isChecked():
return qobj.objectName()
for q_obj in self.toolbox.findChildren(QToolButton):
if q_obj.metaObject().className() == "KoToolBoxButton":
if q_obj.isChecked():
return q_obj.objectName()
raise RuntimeError("No active tool found.")

def _ensure_toolbox(self):
Expand All @@ -63,7 +63,7 @@ def _ensure_toolbox(self):
def _init_toolbox(self) -> QWidget:
"""Find and return reference to unwrapped toolbox object."""
qwindow = self.instance.activeWindow().qwindow()
for qobj in qwindow.findChildren(QWidget):
if qobj.metaObject().className() == "KoToolBox":
return qobj
for q_obj in qwindow.findChildren(QWidget):
if q_obj.metaObject().className() == "KoToolBox":
return q_obj
raise RuntimeError("Toolbox not found.")
2 changes: 1 addition & 1 deletion shortcut_composer/api_krita/wrappers/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def blending_mode(self) -> BlendingMode:

@blending_mode.setter
def blending_mode(self, mode: BlendingMode) -> None:
"""Set blening mode inside this `View` using its enum."""
"""Set blending mode inside this `View` using its enum."""
self.view.setCurrentBlendingMode(mode.value)

@property
Expand Down
2 changes: 1 addition & 1 deletion shortcut_composer/config_system/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Package `config_system` consists of `Field` and `FieldGroup` which grant object-
- reset the value to default.
- register a callback run on each value change.

Type of default value passed on initlization is remembered, and used to parse values both on read and write. Supported types are:
Type of default value passed on initialization is remembered, and used to parse values both on read and write. Supported types are:
- `int`, `list[int]`,
- `float`, `list[float]`,
- `str`, `list[str]`,
Expand Down
2 changes: 1 addition & 1 deletion shortcut_composer/config_system/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Consists of two classes: "Field" and "FieldGroup".
Read the documentation of those classes for more info.
Holds a subpackage with ui elements dependent on the introducad
Holds a subpackage with ui elements dependent on the introduced
configuration concept.
"""

Expand Down
2 changes: 1 addition & 1 deletion shortcut_composer/config_system/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Field(Generic[T]):
- reset the value to default.
- register a callback run on each value change.
Type of default value passed on initlization is remembered, and used
Type of default value passed on initialization is remembered, and used
to parse values both on read and write. Supported types are:
- `int`, `list[int]`,
- `float`, `list[float]`,
Expand Down
12 changes: 6 additions & 6 deletions shortcut_composer/config_system/ui/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


class SpinBoxInterface(Protocol, Generic[F]):
"""Representation of both Qt spinboxes as one generic class."""
"""Representation of both Qt spin_boxes as one generic class."""

def value(self) -> F: ...
def setValue(self, val: F) -> None: ...
Expand All @@ -30,7 +30,7 @@ def setEnabled(self, a0: bool) -> None: ...

class SpinBox(ConfigBasedWidget[F]):
"""
Wrapper of SpinBox linked to a `float` configutation field.
Wrapper of SpinBox linked to a `float` configuration field.
Based on QSpinBox or QDoubleSpinBox depending on the config type.
Works only for fields of type: `int` or `float`.
Expand Down Expand Up @@ -73,7 +73,7 @@ def _init_spin_box(self) -> SpinBoxInterface:


class StringComboBox(ConfigBasedWidget[str]):
"""Wrapper of Combobox linked to a `str` configutation field."""
"""Wrapper of Combobox linked to a `str` configuration field."""

def __init__(
self,
Expand Down Expand Up @@ -111,7 +111,7 @@ def _init_combo_box(self) -> QComboBox:

class EnumComboBox(ConfigBasedWidget[E]):
"""
Wrapper of Combobox linked to a `Enum` configutation field.
Wrapper of Combobox linked to a `Enum` configuration field.
Allows to pick one of enum members.
"""
Expand Down Expand Up @@ -151,7 +151,7 @@ def _init_combo_box(self) -> QComboBox:

class ColorButton(ConfigBasedWidget[QColor]):
"""
Wrapper of QPushButton linked to a `QColor` configutation field.
Wrapper of QPushButton linked to a `QColor` configuration field.
Button displays currently selected color, and clicking activates a
color picker for changing it.
Expand Down Expand Up @@ -196,7 +196,7 @@ def on_click():


class Checkbox(ConfigBasedWidget[bool]):
"""Wrapper of QCheckBox linked to a `bool` configutation field."""
"""Wrapper of QCheckBox linked to a `bool` configuration field."""

def __init__(
self,
Expand Down
4 changes: 2 additions & 2 deletions shortcut_composer/core_components/instructions/layer_hide.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ def on_key_press(self) -> None:

self.document = document
self.affected_node = self.document.active_node
self.affected_node.toggle_visility()
self.affected_node.toggle_visibility()
self.document.refresh()

def on_every_key_release(self, *_) -> None:
"""Change visibility of layer which was active on key press."""
self.affected_node.toggle_visility()
self.affected_node.toggle_visibility()
self.document.refresh()


Expand Down
2 changes: 1 addition & 1 deletion shortcut_composer/data_components/current_layer_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class CurrentLayerStack(list):
Is initialized with `PickStrategy`, which can filter layers based on
their properties (`default: ALL`).
For more info about avaiable strategies, check `PickStrategy`.
For more info about available strategies, check `PickStrategy`.
### Example usage:
```python
Expand Down
2 changes: 1 addition & 1 deletion shortcut_composer/data_components/slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Slider(Generic[T]):
- `controller` -- defines which krita property will be modified
- `values` -- list or range of values to switch to
compatibile with controller
compatible with controller
- `sensitivity_scale` -- (optional) changes sensitivity of slider
- `deadzone` -- (optional) amount of pixels a mouse needs
to be moved for slider to start to work
Expand Down
4 changes: 2 additions & 2 deletions shortcut_composer/input_adapter/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
### Custom keyboard shortcut interface
Package `input_adapter` consists of `ActionManager` and `ComplexActionInterface` which together allow to recognise more keyboard events than usual krita action does.
Package `input_adapter` consists of `ActionManager` and `ComplexActionInterface` which together allow to recognize more keyboard events than usual krita action does.

While usual actions can only recognise key press, implementing `ComplexActionInterface` lets you override methods performed on:
While usual actions can only recognize key press, implementing `ComplexActionInterface` lets you override methods performed on:
- key press
- short key release
- long key release
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def eventFilter(self, _, event: QEvent) -> Literal[False]:
"""
Override filtering method, executed by Qt on every event.
When the event is recognised to be KeyRelease event, run all
When the event is recognized to be KeyRelease event, run all
registered callbacks.
Always return False to let the event reach its desired
Expand Down
Loading

0 comments on commit 48d965a

Please sign in to comment.