Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reload when changing tab #112

Closed
marilmanen opened this issue Jun 4, 2019 · 20 comments
Closed

reload when changing tab #112

marilmanen opened this issue Jun 4, 2019 · 20 comments

Comments

@marilmanen
Copy link
Contributor

File is modified externally and I change the window tab to the externally modified file, I get the "File modified externally" dialog before the tab changes (and at this point I'm confused which file has been modified externally). It would be better to show to the user the old content of the externally modified file and then ask for confirmation of reloading the content (like in NEdit).

@eteran
Copy link
Owner

eteran commented Jun 4, 2019

Hmm, OK. I didn't realize that the original NEdit raised the tab before showing the message. I'll look into a good fix for this.

@eteran
Copy link
Owner

eteran commented Jun 4, 2019

So looking into this... it's complicated. This has to do with the order that Qt delivers events and refreshes. Essentially, the code is getting the "focus changed" event WAY before the repaint event for the tab occurs.

So to address this, I may need to revamp how and when change detection occurs.

I'll definitely keep this on my TODO list since improving that part of the code was something I was looking to do anyway :-)

@tksoh
Copy link
Contributor

tksoh commented Dec 7, 2020

@eteran I've attempted a hack to delay the checking of file stat until after the document has been raised. Please see my branch for the change and see if it's going to work for you. Quite frankly, I'm still struggling to learn about the this signal-slot topic in Qt, so I hope it doesn't break anything:

issue-112-reload-modified-file branch

BTW, my apology for the 'noise' generated by the repeated changes in my branch. I didn't realize github would even include changes in others people's forks into your issue tracker -- not sure why they chose to do that.

@eteran
Copy link
Owner

eteran commented Dec 7, 2020

No worries on the noise. Just happy to have you making contributions!

I'll take a look at this in a little bit!

@eteran
Copy link
Owner

eteran commented Dec 10, 2020

@tksoh I am considering a new approach entirely. Perhaps we can use QFileSystemWatcher or similar to pretty much ALWAYS be notified by the system when a file is changed and we use this to simply set a per document variable of "this has changed behind our backs"

Then, when the tab is given focus, if it happens to have this flag set, we show a message box.

This way, we'd have a lot of control over when it happens.

@tksoh
Copy link
Contributor

tksoh commented Dec 11, 2020

QFileSystemWatcher looks like a interesting feature -- checking for everything manually is a great pain and hard to get right. However, if we still going to have to check the flag, I am unsure how it would change the current implementation. Maybe I am missing something?

@eteran
Copy link
Owner

eteran commented Dec 11, 2020

@tksoh you are right that we still have to figure out when to trigger the message such that it is after a tab is changed, but also after the new tab has been rendered so the new tab is visible.

@tksoh
Copy link
Contributor

tksoh commented Dec 12, 2020

@eteran perhaps instead of checking the flag, the QFileSystemWatcher handler should check to see if the doc is the active one, and pop up the dialog?

@sjtringali
Copy link
Contributor

Yes for QFileSystemWatcher. Note that tabs came late to nedit; there still is some assumption a window == tab. Clearly, in this case we should only be checking on the active tab, and, deferring any popups until the window until the tab is focus and the window is activated.

@sjtringali
Copy link
Contributor

PS you might be looking for the "polish" event.

@eteran
Copy link
Owner

eteran commented Dec 26, 2020

Sadly, the polish event doesn't seem to trigger every time we need it. In my quick and dirty tests of adding a hook for it in DocumentWidget, it only fires the first time the tab is displayed (as far as I can tell), but we really want it to trigger every time a document gets focused. But there certainly is a solution for this, just gotta find it :-).

@eteran
Copy link
Owner

eteran commented Dec 26, 2020

I suppose one thing I could do is instead of checking on the focus event itself... we could just scheduler a check using a QTimer. This would give the even system enough time to finish processing the focus event, and then essentially immediately after, then pop up the messagebox. I'll play with it!

eteran added a commit that referenced this issue Dec 26, 2020
So the problem was that by checking for file changes in the focus event itself, we are popping up
the messagebox BEFORE the focus event is complete. And the update caused by the focus event happens
AFTER it is complete.

So the solution is to NOT check for changes inside the focus event, but instead to schedule
a check for the immediate future. (Done via a single shot timer with a 0 timeout). Inspired
by kernel "bottom half interrupt handlers".

This allows the windowing system to complete processes of existing events, including the repaint
and then will immediately check for changes.

Woot!
@eteran
Copy link
Owner

eteran commented Dec 26, 2020

@marilmanen I believe that this PR creates the behavior that you want!

#227

please confirm when you get a chance.

@sjtringali Absolutely, I plan to switch to QFileSystemWatcher eventually. Any time we can replace a bunch of existing code with a few library calls and get the same results == win! I think to keep the same behavior, we'll have to have the watcher simply set some state flags in the document, since the watcher is always ... watching, even if the tab doesn't have focus :-P.

Then in the focus event, where we currently check for changes, we can just look at the flags, alert as needed, and reset the flag state.

@sjtringali
Copy link
Contributor

sjtringali commented Dec 26, 2020 via email

@eteran
Copy link
Owner

eteran commented Dec 26, 2020

@sjtringali maybe, but that may end up being more complex than the 2 lines for the timer though.

I don't LOVE this solution, but I did have to do it in a couple of other spots in the past to get things to do what we want, and fortunately, Qt hides all of the ugly details of timers from us.

In the end, we just near ANY abstraction for, "do this, but only after you've finished processing outstanding events", and a QTimer::singleShot(0, ...) does that. I'm open to trying fiddling with aync signal connections though. I'll have to think on how it would fit together.

@sjtringali
Copy link
Contributor

sjtringali commented Dec 26, 2020 via email

@eteran
Copy link
Owner

eteran commented Dec 26, 2020

@sjtringali the trouble is that the focus event isn't already captured via a signal. It's an overload instead.

So I **could ** create a "checkModified" signal connect it to a queued connection (I actually had to do that for some of the dialogs "rollback on cancel behavior" already) and then Q_EMIT the signal.

But like I said, this will end up being more complex than the 3 line solution since we'll have to attach the connection on Document construction.

We're talking 3 lines vs 10 5-ish, so it's not a big deal either way. I'll experiment with a signal/slot approach as well, and see if it works out reasonably.

@eteran
Copy link
Owner

eteran commented Dec 26, 2020

@sjtringali actually, I overstated the complexity, LOL. It was pretty trivial to do what you suggest, so now the PR does that instead to seemingly equal effect in fixing this issue :-).

@sjtringali
Copy link
Contributor

sjtringali commented Dec 26, 2020 via email

@marilmanen
Copy link
Contributor Author

I tested PR #227 and it does solve my issue.

eteran added a commit that referenced this issue Dec 27, 2020
* Fixes issue #112!

So the problem was that by checking for file changes in the focus event itself, we are popping up
the messagebox BEFORE the focus event is complete. And the update caused by the focus event happens
AFTER it is complete.

So the solution is to NOT check for changes inside the focus event, but instead to schedule
a check for the immediate future. (Done via a single shot timer with a 0 timeout). Inspired
by kernel "bottom half interrupt handlers".

This allows the windowing system to complete processes of existing events, including the repaint
and then will immediately check for changes.

Woot!

* Following @sjtringali's advice, this is a bit of a cleaner solution since it doesn't need a `QTimer` but has the same effect
@eteran eteran closed this as completed Dec 27, 2020
1div0 pushed a commit to 1div0/nedit-ng that referenced this issue Dec 29, 2020
* Fixes issue eteran#112!

So the problem was that by checking for file changes in the focus event itself, we are popping up
the messagebox BEFORE the focus event is complete. And the update caused by the focus event happens
AFTER it is complete.

So the solution is to NOT check for changes inside the focus event, but instead to schedule
a check for the immediate future. (Done via a single shot timer with a 0 timeout). Inspired
by kernel "bottom half interrupt handlers".

This allows the windowing system to complete processes of existing events, including the repaint
and then will immediately check for changes.

Woot!

* Following @sjtringali's advice, this is a bit of a cleaner solution since it doesn't need a `QTimer` but has the same effect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants