Better layer panel indication of "droppability"
ClosedPublic

Authored by poke1024 on Sep 29 2017, 11:49 AM.

Details

Summary

A ludicrously complex PR for improving the layer panel usability.

Currently the indicator in the layers panel indicates a "can drop inside" (currently a black frame around the layer) for all layers, even though the dropped item may not be put inside the targeted item if actually dropped. What is annoying about this, is that you lose the insertion marker (above and below) as soon as you hover over a layer and you won't know where your insertion ends up.

This PR fixes this by basically checking if a dragged item can actually be inserted into another item. If not, QT will revert to inserting only above and below, i.e. giving you only insertion above and below. This simplifies usage of drag and drop inside the layers panel.

The whole use case is more obvious in conjunction with D8055 that actually displays the "drop inside" indicator as a clearly visible filled box.

The implementation is kind of hacky, unfortunately, but it is, I fear, partially QT's fault (though I'm by no means a QT expert). QT seems to want a definitive info whether an item can be a receiver of a drop (using an item flag called Qt::ItemIsDropEnabled in the KisNodeModel's item). API-wise, this flag is queried without any additional data concerning the current and thus cannot be properly changed or updated depending on the currently dragged data, using QT's API. There is a (model) function canDropMimeData in the QT API that pretends to solve this, but it basically messes up if it returns something else as the flag says (it displays an indicator but fails to perform the drag if you release the mouse, very annoying). So, after experimenting for two days, the best solution seems to be to basically reset all the Qt::ItemIsDropEnabled flags in the model each time a drag is started on the view to the values needed for this specific drag of nodes. To do this, the model needs to be informed about the drag and its contents which necessitates another small hack (using setData and a new property KisNodeModel::DropEnabled).

Diff Detail

Repository
R37 Krita
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
poke1024 created this revision.Sep 29 2017, 11:49 AM
rempt accepted this revision.Sep 29 2017, 2:59 PM
rempt added a subscriber: rempt.

It might be hacky, but it works fine :-)

libs/ui/kis_mimedata.cpp
206

It looks like these changes belong in a separate commit since they seem functionally unrelated to the patch?

This revision is now accepted and ready to land.Sep 29 2017, 2:59 PM

Found a problem that causes a delay when starting to drag a layer that is caused by KisMimeData::loadNodes. Will have to investigate further.

poke1024 updated this revision to Diff 21134.Oct 22 2017, 4:29 PM

Fixes performance problem in KisMimeData::retrieveData by not serializing nodes but using internal nodes instead. The functionality (i.e. namely first calling KisMimeData::tryLoadInternalNodes) now lives in the new function KisMimeData::loadNodesFast; it was originally inside KisMimeData::insertMimeLayers and there was no point in copy pasting that code to the place where the drop functionality now needs it.

Removes one superfluous if condition on shapeController from a preceding experiment.

Fixes wrong indentation on DropEnabled enum.

This revision was automatically updated to reflect the committed changes.
libs/ui/kis_mimedata.cpp
206

Yes, that was part of the experimenting stage where I nulled the shapeController. Removed from the patch now.