Buli Brush Switch

Hi

Currently no, I first need to start to work on this case and, if I’m not able to reproduce it, I’ll need more information at this moment

Yes, seems the same than this bug:

If you have additional information or can confirm it occured (or not) with brushes from disabled bundle

Yes, thanks for feedback, I’ve opened a bug

I need more detail about this case

Grum999

2 Likes

Not from a disabled bundle, but I believe it may be related to a conflicted hotkey. I still had 4 and 5 set to canvas rotation, and tried to set them to brushes in Buli.

It’s hard to say when it happens. Definitely every time Krita is restarted, but it has also happened without closing the program. I’ll keep using it and see if I can spot a pattern!

1 Like

Hi @SchrodingerCat

Currently taking a look on it :slight_smile:

I can confirm there’s something, currently I don’t really know what, but I’m starting to get a better view from where the problem occurs.

With Freehand Brush Tool, on my side it took ~0.05s to switch brush

DEBUG: << Stop:  setBrushActivated[False//True].00 -- (0.05403829  @+0.05414629)

With Dynamic Brush Tool, on my side it took ~0.29s to switch brush

DEBUG: << Stop:  setBrushActivated[False//True].00 -- (0.29191709  @+0.29199147)

It’s not as long as on your side, but hopefully the difference is large enough on my side to be able to try to locate from where the difference come from :slight_smile:

Grum999

1 Like

@SchrodingerCat I’ve made a version v1.0.0, not officially released yet but all commits are pushed on github repository
You can download & install zip plugin from github code with Import python plugin from web… function

And provide following url https://github.com/Grum999/BuliBrushSwitch/archive/refs/heads/v1.0.0.zip

From my tests, switch time has been reduced from ~0.28s to ~0.011s

Can you tell me if it’s better on your side?

Thanks

Grum999

3 Likes

In fact now it feels much faster, now I no longer see the delay :smile:

Thank you so much! :heart:

3 Likes

Great news :slight_smile:

Grum999

2 Likes

Hello thank you for your plugin
I try to select “keep user modification” on a brush. I select it, change the size but when I switch brushes it return to the default settings. Am I missing something?

1 Like

Hi

No

There’s a bug :slight_smile:

It’s fixed but not released yet

Grum999

1 Like

Thank you for quick answer, for your info I had the v1.0.0 installed

1 Like

Which version of v1.0.0? :slight_smile:

Does the downloaded version include the last commit?

As v1.0.0 is not yet released, downloaded content from branch will vary according to date/time

Grum999

1 Like

I downloaded from the link you provided above. I now will wait for the official relase
Thanks

1 Like

It’s more a question of “when” than “where” in our case.
The provided link is a link to branch content.
If you’ve downloaded it before I’ve made the bug fix commit, the option won’t work.
If you’ve downloaded it after the bug fix has been pushed in repository, normally it should work; if not, there’s another problem then

Grum999

1 Like

Doing some additional tests, it seems that it’s not totally fixed… :thinking:
Need to check it…

Grum999

1 Like

I am using Krita 5.1.3 on Win10.
Using the latest version of this script version, an error occurred when starting Krita.
It has been a long time since I enabled Buli Brush Switch, so it is not likely that the error occurred because I used the latest version of Krita.

It appears to be caused by deleting a brush preset that was previously registered in Buli Brush Switch, but I don’t know how to work around it. I keep getting the same error message even after re-installing the script.

TypeError
Python 3.8.1: C:\Program Files\Krita (x64)\bin\krita.exe
Fri Nov 11 03:25:06 2022

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\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushes.py in data(self=<bulibrushswitch.bbs.bbswbrushes.BBSBrushesModel object>, index=<PyQt5.QtCore.QModelIndex object>, role=1)
  946                 if column==BBSBrushesModel.COLNUM_ICON:
  947                     # QIcon
  948                     return QIcon(QPixmap.fromImage(item.image()))
  949         elif role == Qt.ToolTipRole:
  950             id=self.__items[row]
global QIcon = <class 'PyQt5.QtGui.QIcon'>
global QPixmap = <class 'PyQt5.QtGui.QPixmap'>
QPixmap.fromImage = <built-in function fromImage>
item = <BBSBrush(100b0739-35ef-48ab-a5e5-8d990d725da5, 002bb コピー, None)>
item.image = <bound method BBSBrush.image of <BBSBrush(100b0739-35ef-48ab-a5e5-8d990d725da5, 002bb コピー, None)>>
TypeError: fromImage(QImage, flags: Union[Qt.ImageConversionFlags, Qt.ImageConversionFlag] = Qt.AutoColor): argument 1 has unexpected type 'NoneType'
    __cause__ = None
    __class__ = <class 'TypeError'>
    __context__ = None
    __delattr__ = <method-wrapper '__delattr__' of TypeError object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of TypeError object>
    __doc__ = 'Inappropriate argument type.'
    __eq__ = <method-wrapper '__eq__' of TypeError object>
    __format__ = <built-in method __format__ of TypeError object>
    __ge__ = <method-wrapper '__ge__' of TypeError object>
    __getattribute__ = <method-wrapper '__getattribute__' of TypeError object>
    __gt__ = <method-wrapper '__gt__' of TypeError object>
    __hash__ = <method-wrapper '__hash__' of TypeError object>
    __init__ = <method-wrapper '__init__' of TypeError object>
    __init_subclass__ = <built-in method __init_subclass__ of type object>
    __le__ = <method-wrapper '__le__' of TypeError object>
    __lt__ = <method-wrapper '__lt__' of TypeError object>
    __ne__ = <method-wrapper '__ne__' of TypeError object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of TypeError object>
    __reduce_ex__ = <built-in method __reduce_ex__ of TypeError object>
    __repr__ = <method-wrapper '__repr__' of TypeError object>
    __setattr__ = <method-wrapper '__setattr__' of TypeError object>
    __setstate__ = <built-in method __setstate__ of TypeError object>
    __sizeof__ = <built-in method __sizeof__ of TypeError object>
    __str__ = <method-wrapper '__str__' of TypeError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ("fromImage(QImage, flags: Union[Qt.ImageConversio...Color): argument 1 has unexpected type 'NoneType'",)
    with_traceback = <built-in method with_traceback of TypeError 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\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushes.py", line 948, in data
    return QIcon(QPixmap.fromImage(item.image()))
TypeError: fromImage(QImage, flags: Union[Qt.ImageConversionFlags, Qt.ImageConversionFlag] = Qt.AutoColor): argument 1 has unexpected type 'NoneType'
1 Like

Hi @dk8

Thanks for feedback :slight_smile:

This is like this bug, related to disabled bundles/preset

Bug is fixed and available in repository, but not yet released (I’m currently in very slow mode code mode :kiki_upside_down:)

You can follow instructions provided here to get the dev version of future 1.0.0 release:

Grum999

1 Like

I did not properly check the latest contents. My apologies.
I got the following error when installing 1.0.0. The content has changed, so I am reporting it just in case.

TypeError
Python 3.8.1: C:\Program Files\Krita (x64)\bin\krita.exe
Sat Nov 12 01:22:41 2022

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\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bulibrushswitch.py in __windowCreated(self=<bulibrushswitch.bulibrushswitch.BuliBrushSwitch object>)
  103         # is provided by signal)
  104         window = Krita.instance().activeWindow()
  105         installedWindow = BBSWBrushSwitcher.installToWindow(window, PLUGIN_MENU_ENTRY, PLUGIN_VERSION)
  106 
  107     @pyqtSlot()
installedWindow undefined
global BBSWBrushSwitcher = <class 'bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher'>
BBSWBrushSwitcher.installToWindow = <function BBSWBrushSwitcher.installToWindow>
window = <PyKrita.krita.Window object>
global PLUGIN_MENU_ENTRY = 'Buli Brush Switch'
global PLUGIN_VERSION = '1.0.0'

 C:\Users\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py in installToWindow(window=<PyKrita.krita.Window object>, pluginName='Buli Brush Switch', pluginVersion='1.0.0')
   83 
   84             # create BBSWBrushSwitcher instance
   85             returnedBbs = BBSWBrushSwitcher(pluginName, pluginVersion)
   86 
   87             # keep a reference at window level (easier to)
returnedBbs undefined
global BBSWBrushSwitcher = <class 'bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher'>
pluginName = 'Buli Brush Switch'
pluginVersion = '1.0.0'

 C:\Users\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py in __init__(self=<bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher object>, pluginName='Buli Brush Switch', pluginVersion='1.0.0', parent=None)
  191 
  192         self.setLayout(layout)
  193         self.__reloadBrushes()
  194 
  195     def __setSelectedBrushId(self, brushId=None):
self = <bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher object>
self.__reloadBrushes undefined

 C:\Users\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py in __reloadBrushes(self=<bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher object>)
  310                 self.__brushes.add(brush)
  311         self.__brushes.endUpdate()
  312         self.__setSelectedBrushId(self.__selectedBrushId)
  313 
  314     def __displayPopupUi(self):
self = <bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher object>
self.__setSelectedBrushId undefined
self.__selectedBrushId undefined

 C:\Users\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py in __setSelectedBrushId(self=<bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher object>, brushId=None)
  223             # update icon...
  224             brush = self.__brushes.get(self.__selectedBrushId)
  225             self.__tbBrush.setIcon(QIcon(QPixmap.fromImage(brush.image())))
  226             self.__tbBrush.setToolTip(brush.information(BBSBrush.INFO_WITH_BRUSH_DETAILS | BBSBrush.INFO_WITH_BRUSH_OPTIONS))
  227 
self = <bulibrushswitch.bbs.bbswbrushswitcher.BBSWBrushSwitcher object>
self.__tbBrush undefined
global QIcon = <class 'PyQt5.QtGui.QIcon'>
global QPixmap = <class 'PyQt5.QtGui.QPixmap'>
QPixmap.fromImage = <built-in function fromImage>
brush = <BBSBrush(100b0739-35ef-48ab-a5e5-8d990d725da5, 002bb コピー, None)>
brush.image = <bound method BBSBrush.image of <BBSBrush(100b0739-35ef-48ab-a5e5-8d990d725da5, 002bb コピー, None)>>
TypeError: fromImage(QImage, flags: Union[Qt.ImageConversionFlags, Qt.ImageConversionFlag] = Qt.AutoColor): argument 1 has unexpected type 'NoneType'
    __cause__ = None
    __class__ = <class 'TypeError'>
    __context__ = None
    __delattr__ = <method-wrapper '__delattr__' of TypeError object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of TypeError object>
    __doc__ = 'Inappropriate argument type.'
    __eq__ = <method-wrapper '__eq__' of TypeError object>
    __format__ = <built-in method __format__ of TypeError object>
    __ge__ = <method-wrapper '__ge__' of TypeError object>
    __getattribute__ = <method-wrapper '__getattribute__' of TypeError object>
    __gt__ = <method-wrapper '__gt__' of TypeError object>
    __hash__ = <method-wrapper '__hash__' of TypeError object>
    __init__ = <method-wrapper '__init__' of TypeError object>
    __init_subclass__ = <built-in method __init_subclass__ of type object>
    __le__ = <method-wrapper '__le__' of TypeError object>
    __lt__ = <method-wrapper '__lt__' of TypeError object>
    __ne__ = <method-wrapper '__ne__' of TypeError object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of TypeError object>
    __reduce_ex__ = <built-in method __reduce_ex__ of TypeError object>
    __repr__ = <method-wrapper '__repr__' of TypeError object>
    __setattr__ = <method-wrapper '__setattr__' of TypeError object>
    __setstate__ = <built-in method __setstate__ of TypeError object>
    __sizeof__ = <built-in method __sizeof__ of TypeError object>
    __str__ = <method-wrapper '__str__' of TypeError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ("fromImage(QImage, flags: Union[Qt.ImageConversio...Color): argument 1 has unexpected type 'NoneType'",)
    with_traceback = <built-in method with_traceback of TypeError 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\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bulibrushswitch.py", line 105, in __windowCreated
    installedWindow = BBSWBrushSwitcher.installToWindow(window, PLUGIN_MENU_ENTRY, PLUGIN_VERSION)
  File "C:\Users\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py", line 85, in installToWindow
    returnedBbs = BBSWBrushSwitcher(pluginName, pluginVersion)
  File "C:\Users\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py", line 193, in __init__
    self.__reloadBrushes()
  File "C:\Users\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py", line 312, in __reloadBrushes
    self.__setSelectedBrushId(self.__selectedBrushId)
  File "C:\Users\daini\AppData\Roaming\krita\pykrita\bulibrushswitch\bbs\bbswbrushswitcher.py", line 225, in __setSelectedBrushId
    self.__tbBrush.setIcon(QIcon(QPixmap.fromImage(brush.image())))
TypeError: fromImage(QImage, flags: Union[Qt.ImageConversionFlags, Qt.ImageConversionFlag] = Qt.AutoColor): argument 1 has unexpected type 'NoneType'
1 Like

No worries :slight_smile:

This one is weird, I need to dig.

Can you try:

  1. Uninstall the plugin
  2. Rename C:\Users\daini\AppData\Local\krita-plugin-bulibrushswitchrc.json to C:\Users\daini\AppData\Local\krita-plugin-bulibrushswitchrc.json.backup
  3. Install the plugin

Did you still have the error?

Grum999

1 Like

After following the instructions, the error stopped and the functionality became usable. Thank you.

1 Like

Great! :slight_smile:

Can you show me content of .json.backup file?
I think it’s related to problem with deactivated bundles/preset; I fixed the problem for installed plugin but it seems I didn’t think to check what happen on an install for which an old configuration file what still here :slight_smile:

Grum999

1 Like

This is it.

krita-plugin-bulibrushswitchrc.json.backup

{
    "config": {
        "brushes": {
            "default": {
                "lastSelected": "100b0739-35ef-48ab-a5e5-8d990d725da5",
                "modificationMode": "keepModification",
                "selectionMode": "firstFromList"
            },
            "list": {
                "brushes": [
                    {
                        "blendingMode": "normal",
                        "color": "",
                        "colorBg": "",
                        "comments": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style></head><body style=\" font-family:'Sans serif'; font-size:10pt; font-weight:400; font-style:normal;\">\n<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">\u9aea\u306e\u6bdb\u7528\u3000\u308f\u3055\u3063\u3068\u672c\u6570\u63cf\u304f\u30d6\u30e9\u30b7</p></body></html>",
                        "defaultPaintTool": "KritaShape/KisToolMultiBrush",
                        "eraserMode": false,
                        "flow": 1.0,
                        "ignoreEraserMode": true,
                        "keepUserModifications": false,
                        "name": "002bb \u30b3\u30d4\u30fc",
                        "opacity": 1.0,
                        "position": 0,
                        "shortcut": "",
                        "size": 3.33,
                        "uuid": "100b0739-35ef-48ab-a5e5-8d990d725da5"
                    }
                ],
                "count": 1
            }
        },
        "editor": {
            "brushes": {
                "list": {
                    "splitterPosition": [
                        817,
                        408
                    ],
                    "zoomLevel": 3
                }
            },
            "scratchpad": {
                "colorPicker": {
                    "colorCombination": 0,
                    "colorCss": {
                        "visible": false
                    },
                    "colorSlider": {
                        "cmyk": {
                            "asPct": false,
                            "visible": false
                        },
                        "hsl": {
                            "asPct": false,
                            "visible": false
                        },
                        "hsv": {
                            "asPct": false,
                            "visible": true
                        },
                        "rgb": {
                            "asPct": false,
                            "visible": false
                        }
                    },
                    "colorWheel": {
                        "colorPreview": true,
                        "visible": true
                    },
                    "compact": false,
                    "palette": {
                        "default": "Default",
                        "visible": false
                    }
                }
            },
            "text": {
                "colorPicker": {
                    "colorCombination": 0,
                    "colorCss": {
                        "visible": false
                    },
                    "colorSlider": {
                        "cmyk": {
                            "asPct": false,
                            "visible": false
                        },
                        "hsl": {
                            "asPct": false,
                            "visible": false
                        },
                        "hsv": {
                            "asPct": false,
                            "visible": false
                        },
                        "rgb": {
                            "asPct": false,
                            "visible": false
                        }
                    },
                    "colorWheel": {
                        "colorPreview": true,
                        "visible": false
                    },
                    "compact": false,
                    "palette": {
                        "default": "Default",
                        "visible": true
                    }
                }
            },
            "window": {
                "position": {
                    "x": 253,
                    "y": 1515
                },
                "size": {
                    "height": 700,
                    "width": 1241
                }
            }
        },
        "ui": {
            "popup": {
                "brushes": {
                    "list": {
                        "viewMode": 0,
                        "zoomLevel": 2
                    }
                },
                "height": 550,
                "width": 950
            }
        }
    }
}
1 Like