All instructions to download/install it are provided on main plugin page.
Short documentation & screenshots are also provided on github page.
Notes
Beta version & bugs
Provided plugin is a beta version (version 0.2.0b)
Feedback are welcome, but keep in mind this is still a beta version, even if current version seems stable:
There’s some bugs!
– Please also be aware that current version of plugin tweak a little bit the shortcut system as Krita is not aimed to manage dynamic add/remove/update shortcuts information in Settings dialog box.
Requirements
Plugin require Krita 5 and currently, it have only been tested on Krita 5-beta5 Linux appimage
Basic tests made on Windows 10 with Krita 5-beta5
Should work on MacOS too
Add missing .action file (install process now works properly)
Fix invalid default brush definition from settings when no configuration files exists (@Gremriel no more error now… coding-coding, and I didn’t test installation on an environment without plugin configuration file yet… )
On Windows, fix main Brushes list window staying over Brush setting window
*edit: Spoke too soon. The installation error is gone, but as soon as I add a brush ( a) Eraser Soft, in this case) I get an error window that takes a few clicks to go away.
A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.
C:\Users\Gremr\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushes.py in paint(self=<bulibrushswitch.bbs.bbswbrushes.BBSBrushesModelDelegate object>, painter=<PyQt5.QtGui.QPainter object>, option=<PyQt5.QtWidgets.QStyleOptionViewItem object>, index=<PyQt5.QtCore.QModelIndex object>)
1130 painter.fillRect(option.rect, option.palette.color(QPalette.Highlight))
1131
1132 painter.drawPixmap(option.rect.topLeft(), index.data(Qt.DecorationRole).pixmap(option.decorationSize))
1133 painter.restore()
1134 return
painter = <PyQt5.QtGui.QPainter object>
painter.drawPixmap =
option = <PyQt5.QtWidgets.QStyleOptionViewItem object>
option.rect = PyQt5.QtCore.QRect(0, 128, 128, 128)
option.rect.topLeft =
index = <PyQt5.QtCore.QModelIndex object>
index.data =
global Qt = <class ‘PyQt5.QtCore.Qt’>
Qt.DecorationRole = 1
).pixmap undefined
option.decorationSize = PyQt5.QtCore.QSize(128, 128)
AttributeError: ‘NoneType’ object has no attribute ‘pixmap’ cause = None class = <class ‘AttributeError’> context = None delattr = <method-wrapper ‘delattr’ of AttributeError object> dict = {} dir = doc = ‘Attribute not found.’ eq = <method-wrapper ‘eq’ of AttributeError object> format = ge = <method-wrapper ‘ge’ of AttributeError object> getattribute = <method-wrapper ‘getattribute’ of AttributeError object> gt = <method-wrapper ‘gt’ of AttributeError object> hash = <method-wrapper ‘hash’ of AttributeError object> init = <method-wrapper ‘init’ of AttributeError object> init_subclass = le = <method-wrapper ‘le’ of AttributeError object> lt = <method-wrapper ‘lt’ of AttributeError object> ne = <method-wrapper ‘ne’ of AttributeError object> new = reduce = reduce_ex = repr = <method-wrapper ‘repr’ of AttributeError object> setattr = <method-wrapper ‘setattr’ of AttributeError object> setstate = sizeof = str = <method-wrapper ‘str’ of AttributeError object> subclasshook = suppress_context = False traceback =
args = (“‘NoneType’ object has no attribute ‘pixmap’”,)
with_traceback =
The above is a description of an error in a Python program. Here is
the original traceback:
Traceback (most recent call last):
File “C:\Users\Gremr\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushes.py”, line 1132, in paint
painter.drawPixmap(option.rect.topLeft(), index.data(Qt.DecorationRole).pixmap(option.decorationSize))
AttributeError: ‘NoneType’ object has no attribute ‘pixmap’
This is the first time I have seen that shortcut keys can be set elsewhere. Since it will not overwrite but prompts that there are shortcut keys. I think the canvas shortcut keys can be taken into consideration
It was not simple.
Adding a shortcut is not complicated.
Synchronize this shortcut with Krita’s action/shortcut list was not simple.
As I wrote:
– Please also be aware that current version of plugin tweak a little bit the shortcut system as Krita is not aimed to manage dynamic add/remove/update shortcuts information in Settings dialog box.
It works, but I didn’t made strong tests
It works, but I’m pretty sure there might be some case for which you can have problems.
In few words, the tweak is:
Create Action with Krita’s API (this is OK)
Define a shortcut for Action (it works and Krita take it in account)
Update dynamically action file for plugin to set shortcut as default shortcut
On next Krita’s startup, action file is taken in account
The thing is, if you start between steps 2 and 3 to modify manually shortcuts from Krita’s settings, it could have some problem (currently it works, but I don’t want to guarantee that because even if I made test, I didn’t tested all cases)
I’m not really sure.
I didn’t took a look in code, but:
Actions use QAction and QKeySequence for shortcuts (using default KDE user interface)
– An action have a name and can be triggered from anywhere, without knowledge of internal executed method
Canvas Input I think it’s a dedicated Krita’s system, probably based on events (mousePressEvent, mouseReleaseEvent, keyPressEvent, keyReleaseEvent)
– I’m not sure canvas input are named and can be accessed from API
I’m sorry but it’s not clear enough for me to understand at which point the problem occurs.
If you can take times to write steps by step what you do (like I did), possibly with screenshot, it could help me to understand what happen, or how it happen.
My problem is that I currently not able to reproduce it and then, that’s very hard to understand what happens for you.
Can’t tell if you’re the only one.
If someone else can gave me a feedback (works/do not works) that could also help
Ok, as I said in my original post, I installed it per instructions. When Krita launches, the extra button is there. I just did a fresh install of the plugin with the latest version, just in case.
I click it, the window comes up, and I click the Add Brush button. The list of available brushes shows up, and I pick an eraser. I click OK, and then I get all these error messages.
Clicking the close button doesn’t seem to do anything, so I click the X button. More errors show up, I clcik them away, and Krita closes.
I don’t have a clue what the data in the error messages mean, I just report them as I see them.
If you can give me a step by step method to troubleshoot this, I’m happy to test it all out.
One error. It should be because the canvas is not opened
AttributeError
Python 3.8.1: C:\GAMES\STEAM\steamapps\common\Krita\krita\bin\krita.exe
Fri Dec 3 22:02:22 2021
A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.
C:\Users\123\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py in __brushesSelectionChanged(self=<bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcherUi object>, selected=<PyQt5.QtCore.QItemSelection object>, deselected=<PyQt5.QtCore.QItemSelection object>)
498 if len(selectedBrushes)==1:
499 if selectedBrushes[0].found():
500 self.__brushSwitcher.setBrushActivated(selectedBrushes[0])
501 self.hide()
502
self = <bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcherUi object>
self.__brushSwitcher undefined
selectedBrushes = [<BBSBrush({bbb4e7a6-67c5-4622-ab47-5da1c281018d}, 1)Basic old classic)>]
C:\Users\123\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py in setBrushActivated(self=<bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher object>, value=<BBSBrush({bbb4e7a6-67c5-4622-ab47-5da1c281018d}, 1)Basic old classic)>, restoreKritaBrush=True)
385 self.__kritaBrush=BBSBrush()
386 self.__kritaBrush.setIgnoreEraserMode(False)
387 self.__kritaBrush.fromCurrentKritaBrush(saveColor=True)
388 else:
389 # already using brush activated from plugin
self = <bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher object>
self.__kritaBrush undefined
saveColor undefined
C:\Users\123\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushes.py in fromCurrentKritaBrush(self=<BBSBrush({f5d40575-b6ea-44a2-a08d-68c4cc8a103a}, )>, view=<PyKrita.krita.View object>, saveColor=True)
159 brush=view.currentBrushPreset()
160
161 self.__name=brush.name()
162 self.__size=view.brushSize()
163 self.__flow=view.paintingFlow()
self = <BBSBrush({f5d40575-b6ea-44a2-a08d-68c4cc8a103a}, )>
self.__name undefined
brush = None
brush.name undefined
AttributeError: 'NoneType' object has no attribute 'name'
__cause__ = None
__class__ = <class 'AttributeError'>
__context__ = None
__delattr__ = <method-wrapper '__delattr__' of AttributeError object>
__dict__ = {}
__dir__ = <built-in method __dir__ of AttributeError object>
__doc__ = 'Attribute not found.'
__eq__ = <method-wrapper '__eq__' of AttributeError object>
__format__ = <built-in method __format__ of AttributeError object>
__ge__ = <method-wrapper '__ge__' of AttributeError object>
__getattribute__ = <method-wrapper '__getattribute__' of AttributeError object>
__gt__ = <method-wrapper '__gt__' of AttributeError object>
__hash__ = <method-wrapper '__hash__' of AttributeError object>
__init__ = <method-wrapper '__init__' of AttributeError object>
__init_subclass__ = <built-in method __init_subclass__ of type object>
__le__ = <method-wrapper '__le__' of AttributeError object>
__lt__ = <method-wrapper '__lt__' of AttributeError object>
__ne__ = <method-wrapper '__ne__' of AttributeError object>
__new__ = <built-in method __new__ of type object>
__reduce__ = <built-in method __reduce__ of AttributeError object>
__reduce_ex__ = <built-in method __reduce_ex__ of AttributeError object>
__repr__ = <method-wrapper '__repr__' of AttributeError object>
__setattr__ = <method-wrapper '__setattr__' of AttributeError object>
__setstate__ = <built-in method __setstate__ of AttributeError object>
__sizeof__ = <built-in method __sizeof__ of AttributeError object>
__str__ = <method-wrapper '__str__' of AttributeError object>
__subclasshook__ = <built-in method __subclasshook__ of type object>
__suppress_context__ = False
__traceback__ = <traceback object>
args = ("'NoneType' object has no attribute 'name'",)
with_traceback = <built-in method with_traceback of AttributeError object>
The above is a description of an error in a Python program. Here is
the original traceback:
Traceback (most recent call last):
File "C:\Users\123\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py", line 500, in __brushesSelectionChanged
self.__brushSwitcher.setBrushActivated(selectedBrushes[0])
File "C:\Users\123\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py", line 387, in setBrushActivated
self.__kritaBrush.fromCurrentKritaBrush(saveColor=True)
File "C:\Users\123\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushes.py", line 161, in fromCurrentKritaBrush
self.__name=brush.name()
AttributeError: 'NoneType' object has no attribute 'name'