[BUG] Unsaved changes on double click
dreamwhite opened this issue · comments
Steps to reproduce the bug
- Open a
.plist
file - Double click on any text field but DO NOT change the content
- ProperTree reports unsaved changes
Expected behaviour
ProperTree shouldn't report unsaved changes if there's no change (everyone would agree on that :D)
Any possible fix?
Sorry this took awhile to address, I'd been considering it for awhile already, but hadn't gotten around to it until this morening. Can you check this commit and see if it behaves as expected?
-CorpNewt
Hi! It seems partially fixed. I did the following steps:
- Open ProperTree.app with the latest master commit
- Double click on any
String
type field and pressEsc
- ProperTree doesn't report unsaved changes. Correct
BUT if I double click on another String
type field of another dict
entry (e.g. Kernel/Add[0]
and Kernel/Add[1]
), even without any type of changes, it reports that there are unsaved changes. I think you're on the right way to fix it, and I'm very confident about it :)
Here you are a screen recording that may help speed up things
Huh, that super weird. There shouldn't be any difference in the code when double clicking those two dicts but I've likely missed something. I'll look after work and see. Thanks!
Can you try with the latest commit? Still not sure what's going on in the video you uploaded - but I did catch an issue with data values triggering an edit.
-CorpNewt
I just checked but still presents the same issue. Actually it seems that only with DATA
type fields it creates the problem.
Just for the sake of ease, I compared the SHA-1 hashes BEFORE and AFTER the - Edited
in the ProperTree window title, but the hashes are still the same. At this point wouldn't it be easier to display - Edited
only if the hash of the file changes?
Seems like the function that creates the issue is move_selection
despite I do not move any field...
I added print
statements in each function that edits the title, but the only one responsible for making the file appear - Edited
while clearly it isn't (and I'm sure it's not, because of the SHA-1 hashes) is move_selection
. I also tried editing the sensitivity of the dragging dead-zone, without any luck
Yeah - I was considering that may be the case - I'll look into it and see if I can iron that out. I couldn't recreate the issue reliably just by double-clicking to edit, and the double click logic seems sound-enough to me. I'll see what I can do to bullet proof that a bit.
-CorpNewt
Alright - gave it a look, moved the edit check to the confirm_drag()
function instead - and used the self.drag_undo
dict to compare whether or not we've actually moved before setting the doc as - Edited
. Should (hopefully) be fixed as of this commit then.
Please let me know if you find any other issues with it!
-CorpNewt
Hmm - what's odd about that is starting at line 1816, we check if the target cell was moved at all via :
# Make sure we actually moved it somewhere
if self.drag_undo["from"] == node and self.drag_undo["index"] == self._tree.index(target):
return # Didn't actually move it - bail
# We moved it - make sure it shows as edited
if not self.edited:
self.edited = True
self.title(self.title()+" - Edited")
So - the code you've highlighted should not even execute if the table reports that the parent
and index
of the target cell are the same.
Worth noting that I can't recreate the issue here - I can pick up the cell and drag it all over the place, but if I put it back in the same spot - it doesn't mark the doc as - Edited
. It only shows it as edited if the index has changed. Changing scope (i.e. draging the cell into the same index but under another parent) also causes it to show as edited.
I'm currently testing on Windows - but I'll check on macOS as well and see if that behaves differently for me.
Yeah that's the issue... It actually executes the code even if it shouldn't. I don't know if this may help you fixing the issue, but from what I see, it moves the cell from one index to another:
DEBUG: Editing title from confirm_drag function
HEY IT'S INSIDE HERE THE BUG
[{'type': 'move', 'cell': 'I17A', 'from': 'I18F', 'to': 'I171', 'index': 1}]
[{'type': 'move', 'cell': 'I17A', 'from': 'I18F', 'to': 'I171', 'index': 1}, {'type': 'edit', 'cell': 'I17A', 'text': 'Base', 'values': ('⇕ Data', '<FF0000FF FFFFFFFF FFFFFFFF>', '≡')}]
I added the print
statements just to make sure that I'm reproducing the bug correctly
Can you add this line right before the if self.drag_undo["from"]...
line at 1816 and show me what it prints?
print(target, self.drag_undo["from"], node, self.drag_undo["index"], self._tree.index(target))
Sure, let me reproduce the bug again. Luckily it takes a lot of double-click testing than before. We're on the right path I think
KeyError: 'print'
. Let me fix it hold on
I just tested on macOS (13.1 b4) with the current code base and it worked as expected. I could drag an entry all over the place and drop it back where it was originally - and the doc wouldn't show that it had been edited. When I drop it to a new location, it shows as - Edited
as expected. I'm not sure how double clicking changes things yet though.
Also - sorry, that key error was my issue - edited my prior message.
Yeah no worries, I changed it with from
. Let me test it and report you back the values
I17A I171 I171 8 8
is the output
And it still executes the code under? I171
== I171
and 8
== 8
, so that if statement should prevent it from progresing.
If adding self.edited = False
there has an effect - than the code underneath that if statement shouldn't run - as we already have a return
there - which returns from the function entirely. I'm wondering if there's some sort of race condition at play - and either setting self.drag_undo
or self.dragging
is happening too late. However, if it never printed anything implying the from and index values were different - I'm not sure where that's applying - as we should be able to log that still.
I think it's a matter of race condition at this point with self.drag_undo
function... Should I keep this little hack
in the code to fix it or there's a better approach? I'm definitely not a ProperTree maintainer neither a Python expert, but that's the only thing that made the code properly work
That making the code work doesn't really make sense though - as it's immediately evaluated in the next line if the function didn't return:
# We moved it - make sure it shows as edited
if not self.edited:
self.edited = True
self.title(self.title()+" - Edited")
And if we turn off the self.edited
, but the file had already been edited, the title would become - Edited - Edited
- which just adds another bug. I'll see if I can reorder when the drag locks are applied to avoid any sort of race conditions.
Alright - I rearranged some things and implemented some earlier global setting in this commit - maybe that will help some. Please test and let me know.
The thing I think will fix it (if it's fixed) is resetting the self.drag_undo
as soon as we start a new drag instance - as well as checking for a NoneType
drag_undo within the drag completion handler:
# 1752
if self.drag_start == None:
# Let's set the drag start globals
self.drag_start = (event.x, event.y)
self.drag_undo = None
self.dragging = True
return
and:
# 1808
def confirm_drag(self, event):
if not self.dragging or not self.drag_undo:
return
-CorpNewt
YES IT WORKS!!! Sadly I can only test on macOS. Have you checked that the issue seems fixed also in Win and Linux?
I just checked but still presents the same issue. Actually it seems that only with
DATA
type fields it creates the problem. Just for the sake of ease, I compared the SHA-1 hashes BEFORE and AFTER the- Edited
in the ProperTree window title, but the hashes are still the same. At this point wouldn't it be easier to display- Edited
only if the hash of the file changes?
Just as a side note on this - it's possible, but would require serializing the plist, then gathering a checksum every time something may or may not be changed - which could end up being very slow on larger plists, slower hardware, or with users that make quick edits (or even just enter
then esc
a ton). I'm hoping to be able to just catch any changes the user might make, apply some simple-ish checks to see if we actually changed anything - then apply the - Edited
as needed.
YES IT WORKS!!! Sadly I can only test on macOS. Have you checked that the issue seems fixed also in Win and Linux?
Perfect! As for Windows and Linux - I've not even been able to reproduce the double-click/drag-oriented issue locally, so I've just been going off your debugging, and I don't personally use Linux so that will have to be checked by other users I suppose.
The changes are pushed though - and I'll leave this issue open for awhile in case anyone else runs into it - but if it goes a couple weeks without additions, I'll consider it closed.
Thanks for testing, glad we got it ironed out. Let me know if you run into other oddities!
-CorpNewt