keepassxc icon indicating copy to clipboard operation
keepassxc copied to clipboard

TagsEdit code improvements

Open libklein opened this issue 1 year ago • 9 comments

Fix bug where pressing home on empty tag field crashes the program.

Bug is caused by https://github.com/libklein/keepassxc/blob/develop/src/gui/tag/TagsEdit.cpp#L340. The currentText().isEmpty() allows to invalidate the invariant if the current (and only) tag is empty. In this case, tags is resized to 0 (the only tag is erased) and the program crashes as currentText() accessed in https://github.com/libklein/keepassxc/blob/develop/src/gui/tag/TagsEdit.cpp#L504 fails as the tags list is now empty (https://github.com/libklein/keepassxc/blob/develop/src/gui/tag/TagsEdit.cpp#L387).

  • ✅ Bug fix (non-breaking change that fixes an issue)

libklein avatar Oct 10 '24 22:10 libklein

I've attempted to do some basic refactoring of the class. I've moved responsibility for keeping track of the current item, as well as maintaining the invariant into a dedicated "TagManager" class. This class avoids the index-tracking issues by using a QLinkedList rather than a QList, that we way never invalidate any iterators.

I've further attempted to have a clear split in responsibility between Impl and TagsEdit. Impl contains the tag handling logic, TagsEdit listens to events and calls Impl functions accordingly. I suggest merging Impl and TagsEdit, the only reason for having Impl in the first place was, I assume, to have a stable header API (PImpl).

I've further fixed a few minor bugs in the implementation:

  • There was a corner case where an empty tag could be rendered when TagsEdit went out of focus with an empty tag selected
  • Scrollbars were not updated after removing a tag
  • Tags were not re-rendered (and re-layouted!) when ";" is pressed on an empty tag.

There is still a bug with rendering - the height hint of the textbox is wrong on first render - and a bit of cleanup needs to be done. I'd however like to get feedback on the general approach before polishing.

Another open question is the behavior of typing ";", which currently finishes editing the current tag. I think it's a bit unintuitive that this always finishes the current tag, regardless of cursor position. I'd expect the tag to be split if I type ";" in the middle of a tag.

What do you think? Any idea why the initial height hint may be off?

libklein avatar Nov 27 '24 20:11 libklein

Thank you for this work! I do agree that typing a ; or , should cause the tags to be split instead of ending typing immediately. But what about pressing space, that also ends tag typing. That could also help with pasting tag strings.

droidmonkey avatar Nov 27 '24 21:11 droidmonkey

@libklein sorry just coming back to this. I made a bunch of code improvements to align with our standards. Also noticed that now the tags view when editing an entry gets cut off when first shown:

image

The view expands vertically when focused to not be cut off. Not sure where in the list of changes this happened.

droidmonkey avatar Dec 21 '24 21:12 droidmonkey

  1. Looks like too much vertical padding on the tag labels (inside the green rectangles).
  2. Could reduce at least the vertical padding of the outer text box (outside the green rectangles).
  3. The text box is shifted inward from its gray border, which makes the text box less tall, and shifts it sideways. (On closer look, the other textboxes have that border too, but the black area is not shifted.)

michaelk83 avatar Dec 22 '24 08:12 michaelk83

@michaelk83 those are not the causes. I put a bunch of time into diagnosing this and we were basically fighting Qt for sizing. I have a WIP commit added that improves the situation substantially and allows for external styling of the tags display instead of overriding everything internally.

image

image

~~Note: This still needs work because editing and adding tags is now broken. The fix is to separate actual painting of the widget from height estimation, the two are stuck together now and the logic is broken.~~ FIXED

droidmonkey avatar Dec 22 '24 15:12 droidmonkey

TODO:

  • [ ] Combine the TagsEdit::Impl directly into TagsEdit. There is no reason to have these separate and it creates ugly code
  • [ ] TagsManager should do all things non-gui related to the tags, including non-gui tag editing functions
  • [ ] Make a proper viewport height calculation function

droidmonkey avatar Dec 23 '24 04:12 droidmonkey

Going to save this refactor for 2.8.0, created a new compact crash fix for 2.7.10: https://github.com/keepassxreboot/keepassxc/pull/11625

droidmonkey avatar Jan 04 '25 21:01 droidmonkey

@droidmonkey Sorry, I did not have time to look into this since December.

If we have time to do a large refactor, then I'd suggest replacing the apparently brittle custom rendering logic altogether. Is there any reason to not implement TagsEdit as a container that nests custom QTextEdits? That would allow to have rich text support etc.

libklein avatar Jan 12 '25 12:01 libklein

I was thinking the same thing @libklein. There is plenty of time on this branch/PR since it is targeting 2.8.0 now. We merged the break/fix for the HOME button crash already.

droidmonkey avatar Jan 12 '25 13:01 droidmonkey