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 #274540: save user choice of instrument genre #3830
fix #274540: save user choice of instrument genre #3830
Conversation
748ceb7
to
6aed008
Compare
mscore/instrwidget.cpp
Outdated
@@ -362,6 +362,8 @@ QString InstrumentTemplateListItem::text(int col) const | |||
InstrumentsWidget::InstrumentsWidget(QWidget* parent) | |||
: QWidget(parent) | |||
{ | |||
storeChangeInGenre = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed?
Couldn't it be set directly to true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This variable is needed because when the InstrumentsWidget is being created, the selected instrument genre is changed by some other scripts a couple of times. I want to be able to save changes to the genre, but only ones made by the user. So, when loading is complete and this variable has been set to true, only then will any genre changes made be stored, because they are user-made changes, not automatic ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable isn't needed though if you see my reply below I guess
mscore/instrwidget.cpp
Outdated
if ( ! settings.value("selectedInstrumentGenre").isNull() ){ | ||
int selectedGenre = settings.value("selectedInstrumentGenre").value<int>(); | ||
instrumentGenreFilter->setCurrentIndex(selectedGenre); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these last lines are not needed.
just use
instrumentGenreFilter->setCurrentIndex(settings.value("selectedInstrumentGenre", /*default value, probably 0*/ 0).toInt());
same for in SelectInstrument.cpp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default is whatever index 'common' has, since that's what it gets set to in some script (I can't remember which one). This creates a problem, because the index of common could change, but the default should still be common. So, to avoid having to look up the index of t default, it's easier and simpler to just check whether the selectedInstrumentGenre is set and then leave the filter as the default value if not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right about that
mscore/instrwidget.cpp
Outdated
if (storeChangeInGenre){ | ||
settings.setValue("selectedInstrumentGenre", index); | ||
settings.sync(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couldn't these settings be saved in the destructor?
They would only be saved once, and there would be no need for the storeChangeInGenre private variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point actually. I can't test it right now, but I seem to remember that if you access the value of a setting after it's been changed but not synced, it will have the last synced value. The variable would be unneeded, I guess because:
- The widget is initialized
- The genre settings value is changed a couple of times automatically but not synced
- The genre filter is set to the genre settings value (but the last saved one, which would be user chosen)
- This change in genre filter is saved to the genre settings variable (meaning that any automatic genre changes are basically ignored)
- User possibly changes genre
- Widget closes, last chosen genre is saved
Sounds good to me. Basically, you're right :)
Thanks for your review @Marr11317. Unfortunately I'll be unable to implement any changes for the next 3 weeks, but your feedback is very useful. |
6af1486
to
af96235
Compare
Feedback addressed, a final review would be appreciated @Marr11317 (or anyone else) |
mscore/instrwidget.cpp
Outdated
{ | ||
QSettings settings; | ||
settings.sync(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't you simply save the index in the destructor?
you would have this kind of destructor:
InstrumentsWidget::~InstrumentsWidget()
{
QSettings settings;
settings.beginGroup(objectName());
settings.setValue("selectedInstrumentGenre", instrumentGenreFilter->index());
settings.endGroup();
}
and such a constructor
InstrumentsWidget::InstrumentsWidget()
{
...
QSettings settings;
settings.beginGroup(objectName());
if ( ! settings.value("selectedInstrumentGenre").isNull() ){
int selectedGenre = settings.value("selectedInstrumentGenre").toInt();
instrumentGenreFilter->setCurrentIndex(selectedGenre);
}
settings.endGroup();
...
}
That way, no need for saving it every time the index changes. It will simply be saved on destruction, and initialised on construction.
Plus, here Qt's doc about QSettings::sync()
The settings are already synced in the destructor so there shouldn't be any need for line 1073 here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review. You're right, the settings value could be written in the destructor. I'm a bit new to C++ so I don't know the ins and outs of it very well yet, so your feedback really helps :)
mscore/selinstrument.h
Outdated
@@ -50,6 +50,7 @@ class SelectInstrument : public QDialog, private Ui::SelectInstrument { | |||
public: | |||
SelectInstrument(const Instrument*, QWidget* parent = 0); | |||
const InstrumentTemplate* instrTemplate() const; | |||
~SelectInstrument(); | |||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as upper
Here's a few things you could also do around:
|
Actually, I think the index should not be saved as an ///constructor:
//...
QSettings settings;
settings.beginGroup(objectName());
if ( ! settings.value("selectedInstrumentGenre").isNull() ){
QString selectedGenre = settings.value("selectedInstrumentGenre").toString();
instrumentGenreFilter->setCurrentText(selectedGenre);
}
settings.endGroup();
//...
///and the destructor:
//...
QSettings s;
s.beginGroup(objectName());
s.setValue("selectedInstrumentGenre", instrumentGenreFilter->currentText());
s.endGroup();
//... |
I don't think it should because you could have the reverse of the problem you're talking about: you're worried that instrument genre indices may change, but what about the instrument genre names? Surely those could change as well, and if they do then there would be a similar problem. Because of this, I'm going to stick with saving the index. |
55fb1e9
to
6da831c
Compare
Any final review needed @Marr11317 ? |
But then, if the string changes, and so the saved string is not found, the index will be set to 0, which means general instruments. But if new instruments lists are added, and you try to put the index to let's say 3, It could be something completely random such as "Indian folk instruments of the nineteenth century" |
InstrumentsWidget* iw = new InstrumentsWidget();
iw->setObjectName("Some new specific name"); And now the values won't be saved at the same place because connect(this, &QObject::objectNameChanged, this, &InstrumentsWidget::readSettings); So could you just change these |
The whole point of this feature request is so that the genre is the same. It doesn't make sense to have it different in different dialogues. The genre, when changed in the 'add instrument' windows, should also change in the 'change instrument' window (for changing the instrument of a stave). The reasoning being that when working on a project with a particular genre of instruments you don't want to have to keep changing the genre, neither when you're adding an instrument nor when you're changing one. So, the value must be saved in the same place, something that can't be done across objects using the |
looks good to me. |
@Marr11317 after some investigation, I've found out that things aren't as simple as they might be :/ The instruments widget doesn't ever destruct during runtime - it constructs once, when first opened, then destructs once when the program closes. The select instrument window, on the other hand, does construct every time when opened, and destructs every time it's closed. I'm going to have to go back to writing and syncing in the |
6da831c
to
bcd67b5
Compare
@Marr11317 (one final review maybe?) Right. This should be the final commit. Things have had to be changed a bit - as I said before, the Instrument Dialog wasn't being destroyed on close. Now, it is destroyed on close, but it's not simple, because sometimes the Instrument Widget (a child of the Dialog) needs to persist for a while after closure to allow instrument changes to be made. So the, Dialog needs to be closed at different points in the code depending on if a change has been made or not (and so it needs to happen in the |
767720e
to
7d18eb3
Compare
mscore/musescore.cpp
Outdated
{ | ||
if (instrList){ | ||
// ugly, but instrList->done(1) doesn't work, so instrList must be directly destroyed | ||
instrList->~InstrumentsDialog(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about delete instrList;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, yes that would be better 🤦♂️
7d18eb3
to
3e1903f
Compare
There, all done @Marr11317 . Ready for merge now @anatoly-os ? |
Rebase needed, conflict should not be too difficult to fix |
3e1903f
to
cb982cd
Compare
Accidently force-pushed branch without committing 🤦♂️ |
This PR is outdated. The code is also badly written. I will rewrite it, and open a new PR, and as such I am closing this one. |
This addresses a feature request at: https://musescore.org/en/node/274540
The request was to keep the user's selection of instrument genre so that they don't have to change it every time they add/change an instrument. This PR adds this functionality by saving the user's last choice of instrument in QSettings, which actually means that the last selected genre will be saved even after the application has closed.