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

Fix library track selection, save model state #4177

Merged
merged 12 commits into from
Nov 20, 2021

Conversation

ronso0
Copy link
Member

@ronso0 ronso0 commented Aug 4, 2021

This is an attempt to cherry-pick commits from @poelzi's #3063 to fix the library track selection only
(save/restore selection, focus and scroll position per model view).

I guess this will take some time due to short free time, some merge conflicts, building each commit etc.


TODO

  • Browse/computer: store selected directory
  • fix inconsistent save/restore when activating active sidebar item
  • make use of noSearch parameter

@ronso0 ronso0 added this to the 2.4.0 milestone Aug 4, 2021
@ronso0 ronso0 marked this pull request as draft August 4, 2021 23:05
@coveralls
Copy link

coveralls commented Aug 4, 2021

Pull Request Test Coverage Report for Build 1137229790

  • 0 of 189 (0.0%) changed or added relevant lines in 25 files are covered.
  • 27 unchanged lines in 12 files lost coverage.
  • Overall coverage decreased (-0.06%) to 25.909%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/library/recording/recordingfeature.cpp 0 1 0.0%
src/library/baseexternalplaylistmodel.cpp 0 2 0.0%
src/library/mixxxlibraryfeature.cpp 0 2 0.0%
src/library/proxytrackmodel.cpp 0 2 0.0%
src/library/recording/dlgrecording.cpp 0 2 0.0%
src/library/rhythmbox/rhythmboxfeature.cpp 0 2 0.0%
src/library/serato/seratofeature.cpp 0 2 0.0%
src/library/trackset/crate/cratefeature.cpp 0 2 0.0%
src/library/browse/browsefeature.cpp 0 3 0.0%
src/library/traktor/traktorfeature.cpp 0 3 0.0%
Files with Coverage Reduction New Missed Lines %
src/engine/enginevumeter.cpp 1 90.24%
src/library/baseexternalplaylistmodel.cpp 1 0%
src/library/browse/browsetablemodel.cpp 1 0%
src/library/library.cpp 1 0%
src/library/recording/recordingfeature.cpp 1 3.33%
src/library/trackset/baseplaylistfeature.cpp 1 0%
src/library/trackset/crate/cratetablemodel.cpp 1 0%
src/widget/wlibrary.cpp 1 0%
src/library/browse/browsefeature.cpp 2 0.42%
src/widget/wlibrarytableview.cpp 3 0%
Totals Coverage Status
Change from base Build 1137013267: -0.06%
Covered Lines: 19985
Relevant Lines: 77136

💛 - Coveralls

@ronso0 ronso0 force-pushed the lib-selection-state branch 5 times, most recently from 4b98db8 to 10bda6b Compare August 7, 2021 01:19
@ronso0
Copy link
Member Author

ronso0 commented Aug 7, 2021

Alrighty, I think this is now in a good shape.
ToDos are in the 1st post, primarily restore functionality to re/store the selected Browse directory.
Anyone who has reviewed #3063 is invited to take a look at this : )

While debugging a crash I noticed that restoreTrackModelState
a is called on already selected models
b is called twice fixed for Tracks

Another issue (needs to be double-checked, also with main):
. select any track in Tracks
. go to AutoDJ, fill the list so it has more tracks than fit in the view, scroll down, select some track near the bottom
. go to any crate that has more tracks than fit in the view
= initial view is scrolled down

Apart from that it works great!

@ywwg Feel free to build the header functions on top (sort order, individual headers etc.)

@ronso0 ronso0 marked this pull request as ready for review August 7, 2021 01:27
@ronso0 ronso0 changed the title [WIP] Fix library track selection, save model state Fix library track selection, save model state Aug 7, 2021
@ronso0 ronso0 requested a review from uklotzde August 7, 2021 01:27
@ronso0
Copy link
Member Author

ronso0 commented Aug 7, 2021

right now the commit history still contains a lot of back and forth experiments.
I'll wrap my head around how to merge those to the essentials. If desired...

@ronso0 ronso0 marked this pull request as draft August 7, 2021 10:54
src/widget/wlibrary.cpp Outdated Show resolved Hide resolved
src/library/trackmodel.h Outdated Show resolved Hide resolved
@ronso0 ronso0 force-pushed the lib-selection-state branch 3 times, most recently from 287d72f to a1427f8 Compare August 8, 2021 21:19
@ronso0
Copy link
Member Author

ronso0 commented Aug 9, 2021

I'm splitting the overall final changes into easily digestible bits, so don't start reviewing, yet.

@uklotzde
Copy link
Contributor

Please fix the conflicts for testing.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for picking this up.

I have added som suggestions, not found real issues. I will do also a manual test soon.

src/library/baseexternalplaylistmodel.cpp Show resolved Hide resolved
src/library/baseexternalplaylistmodel.cpp Outdated Show resolved Hide resolved
if (noSearch) {
return QStringLiteral("table:") + m_tableName;
}
return QStringLiteral("table:") + m_tableName +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same here.
We also may consider to move this function into the base class and fetch only the prefix via an overloaded virtual function.

Copy link
Member Author

@ronso0 ronso0 Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the modelKey() function is identical for most models, except Browse, Crate, BaseExternalPlaylistModel and Proxy..
So I wonder if it's worth the effort.
Fo rmy taste it's optimized sufficiently if the model prefix becomes a const in the namespaces.

src/library/browse/browsetablemodel.cpp Outdated Show resolved Hide resolved
VERIFY_OR_DEBUG_ASSERT(!key.isEmpty()) {
return;
}
ModelState* state = m_modelStateCache.take(key);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use .object() her which keeps the state object int the cache but moves it to the top.
If it returns null we can immediately insert the new element.
This avoids to move the ownership of the created object around and is probably a bit faster.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, the original commit 49d263e is tagged "Make QCache usage safe against concurrent deletion", though I don't see when that would happen.
I guess @poelzi can explain his motivation for this change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is open. I think we should use the normal pattern for QCache here unless we can remember the reason and put that into the code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It follow the logic that the Object in the QCache is only ever owned by one owner, rust style. It is either in the update handler or in the QCache object, but it is never in the update handler while the QCache thinks it needs to drop this object.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the warning in the QCache docs, if you just get a pointer:
Warning: The returned object is owned by QCache and may be deleted at any time.
If I remember correctly, I could provoke a crash by very fast switching between different models, I was able to cause a crash.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay. could you add a review/code suggestion that adds a comment with this explanation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Warning applies applies, if you store the pointer in a member variable, or if we use the cache from multiple threads.
The QCrash has no magic to do something at laterally any time. It can do something at any call.
All this does not apply here. So I am not able to write a reasonable comment. I assume the crashes was cased by something else.

However since this is only a minor issue, and not on a performance critic path, I think we should keep this tested variant, but not add a comment with probably wrong assumptions.

@daschuer
Copy link
Member

I have just give this a brief test. I think it works like it should from the code, but it does not feel correct.

Let's say I select a track "Nickelblack".
Than I search for "ABBA" and select an ABBA track.
Than I want to check which track was released at the same time.
Sort for date
Remove the search filter
"Nickelblack" is selected :-(

This not a regression here, but I like to know if you can confirm it.
Do we need also consider other use cases?

@ronso0
Copy link
Member Author

ronso0 commented Oct 31, 2021

can't test this right now, but yeah I think that's the current behavior of onSearch() and @poelzi addressed the issue with 7b9e405
I didn't pick that commit because I experienced issues with it which I didn't debug yet.
and I didn't wrap my head around the actual query parser functions tbh.

@poelzi
Copy link
Contributor

poelzi commented Nov 1, 2021

yes. with that commit it is decided if a search term is a reduced search, aka, is less sepecific. In this case, the selected track will be in the selection and therefor should keep it's selection. This felt correct when testing.

@ronso0
Copy link
Member Author

ronso0 commented Nov 3, 2021

If reviews of the current state don't bring any issues to light I can continue to pick more of @poelzi's commits to improve the situation further. Though, I'll have to delve into the search parser stuff to somewhat know what I'm doing, and debug issues I ran into during previous attempts.
Or we do that in another PR. I don't mind.

@daschuer
Copy link
Member

daschuer commented Nov 4, 2021

I would prefer to merge this soon and go in smaller steps. This has no regression to main so it should be possible.

The QCache usage is open and the CI failure.

@ronso0
Copy link
Member Author

ronso0 commented Nov 4, 2021

re CI failure
why does glang-format scan unchanged lines? it didn't do so when run locally, and it didn't complain about the missing line breaks in the newly added lines.
Also I don't think the line break is helpful. the one-line, empty virtual functions are much easier to read without it.

@Be-ing Be-ing requested a review from daschuer November 13, 2021 23:39
@Be-ing
Copy link
Contributor

Be-ing commented Nov 13, 2021

Is there anything left to do here?

@ronso0
Copy link
Member Author

ronso0 commented Nov 15, 2021

adding a comment explaining why the state is taken from the QHash, populated and re-inserted afterwards.
#4177 (comment)
@daschuer You noticed anything else?

@ronso0
Copy link
Member Author

ronso0 commented Nov 20, 2021

ping @daschuer

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM,
Thank you @ronso0 for picking it up.

VERIFY_OR_DEBUG_ASSERT(!key.isEmpty()) {
return;
}
ModelState* state = m_modelStateCache.take(key);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Warning applies applies, if you store the pointer in a member variable, or if we use the cache from multiple threads.
The QCrash has no magic to do something at laterally any time. It can do something at any call.
All this does not apply here. So I am not able to write a reasonable comment. I assume the crashes was cased by something else.

However since this is only a minor issue, and not on a performance critic path, I think we should keep this tested variant, but not add a comment with probably wrong assumptions.

@daschuer daschuer merged commit a7a6a08 into mixxxdj:main Nov 20, 2021
@ronso0
Copy link
Member Author

ronso0 commented Nov 20, 2021

🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog This PR should be included in the changelog library ui
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

7 participants