SUMMARY The python Channel.setVisible() scripting call does not behave as expected. Rather than individually addressing the specified channel's visibility, it affects all other channels' visibilities too. STEPS TO REPRODUCE 1. Start Krita 2. Create a new blank document 3. Open the Tools->Scripts->Scripter 4. Run the following script in the scripter: from krita import * activeView = Krita.instance().activeWindow().activeView() activeDocument = activeView.document() activeNode = activeDocument.activeNode() for i in range(4): activeNode.channels()[i].setVisible(False) 5. Open the layer's properties dialog 6. Observe the active channel status OBSERVED RESULT All three color channels are active (ticked), only the alpha channel is inactive (unticked) EXPECTED RESULT All four channels should be inactive (unticked) SOFTWARE/OS VERSIONS Windows: Not tested macOS: Catalina 10.15.6: Tested, bug is always reproducible Linux/KDE Plasma: Not tested (available in About System) KDE Plasma Version: NA KDE Frameworks Version: NA Qt Version: NA ADDITIONAL INFORMATION Further testing shows that whenever a setVisible(X) call is made on a channel, all other channel visibilities are reset to true, and only the last channel's visibility is correctly set.
Proposed cause of bug: The code in the setVisible method in libs/libKis/Channel.cpp looks as follows: void Channel::setVisible(bool value) { if (!d->node || !d->channel) return; if (!d->node->inherits("KisLayer")) return; for (uint i = 0; i < d->node->colorSpace()->channelCount(); ++i) { if (d->node->colorSpace()->channels()[i] == d->channel) { QBitArray flags = d->node->colorSpace()->channelFlags(true, true); flags.setBit(i, value); KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data()); layer->setChannelFlags(flags); break; } } } From a look into the call QBitArray flags = d->node->colorSpace()->channelFlags(true, true); it appears that this does not return the current status (active/inactive) of the layer's channels, rather it simply returns the "kind" of each channel in the colorspace, ie. whether it is a color channel or an alpha channel. Rather, the flags should be fetched using QBitArray flags = layer->channelFlags(); Modifying the code in setVisible() to read void Channel::setVisible(bool value) { if (!d->node || !d->channel) return; if (!d->node->inherits("KisLayer")) return; + KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data()); + QBitArray flags = layer->channelFlags(); + if (flags.isEmpty()) { + flags.fill(1, d->node->colorSpace()->channelCount()); + } + for (uint i = 0; i < d->node->colorSpace()->channelCount(); ++i) { if (d->node->colorSpace()->channels()[i] == d->channel) { - QBitArray flags = d->node->colorSpace()->channelFlags(true, true); flags.setBit(i, value); - KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data()); layer->setChannelFlags(flags); break; } } } has the desired outcome of *only* affecting the channel in question. The python code in the original bug post now works as intended.
Git commit 74f77fc01cefed9261b59cc827927f11e36b2aae by Halla Rempt, on behalf of Chris Venter. Committed on 28/01/2021 at 13:22. Pushed by rempt into branch 'master'. Use layer->channelFlags in libkis Channel.cpp to correctly retrieve the current channel visibility M +6 -2 libs/libkis/Channel.cpp https://invent.kde.org/graphics/krita/commit/74f77fc01cefed9261b59cc827927f11e36b2aae
Git commit 1d22acfd3cacb3ee7717dc4958295aeba0cfe09c by Halla Rempt, on behalf of Chris Venter. Committed on 28/01/2021 at 13:24. Pushed by rempt into branch 'krita/4.3'. Use layer->channelFlags in libkis Channel.cpp to correctly retrieve the current channel visibility (cherry picked from commit 74f77fc01cefed9261b59cc827927f11e36b2aae) M +6 -2 libs/libkis/Channel.cpp https://invent.kde.org/graphics/krita/commit/1d22acfd3cacb3ee7717dc4958295aeba0cfe09c