corpnewt / ProperTree

Cross platform GUI plist editor written in python.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] Unsaved changes on double click

dreamwhite opened this issue · comments

Steps to reproduce the bug

  1. Open a .plist file
  2. Double click on any text field but DO NOT change the content
  3. 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:

  1. Open ProperTree.app with the latest master commit
  2. Double click on any String type field and press Esc
  3. 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

Sadly it doesn't work... Still the same issue, but this time is inside confirm_drag function

image

I'm trying to isolate the problem in the function and seems like the issue is there:

image

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.

Exactly. I think I actually fixed it as depicted below. Don't know if it's the right approach tho...

image

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