Redesign of preferences window

• Nov 8, 2017 - 06:38

I've just added a new setting in the preferences window in a pull request. I then saw lasconic's comment in regarding the preferences window and adding new settings there. He suggests a redesign of the preferences window e.g. like a searchable list of settings.

How would you change the preferences window to make it more user friendly, searchable and easy to navigate?

PS: Is there any ongoing work on this already?


My point was not to refactor the existing, but to add another way to access all preferences. Currently some properties are actually easily changeable in the code (the voice colors for example) and have even preference keys but they is not UI for them. I believe it's not a good idea to have a full blown UI for them. I would prefer to have a clean and simple UI for the most used properties (basically the ones we have right now) and a list (a la firefox) for all properties (most used + obscure) a la firefox about:config. This second interface would not necessary be more "user friendly" but definitely searchable and easy to navigate.

As far as I know, no one is working on this.

In reply to by [DELETED] 5

So a new tab "Advanced" (or whatever) in the Preferences window with a searchable list of preferences would be the way to go?

Do you think this list should contain all preferences? I ask because some preferences require quite a lot special code just for a single preference. E.g. the Input/Output tab: I don't think it would be wise to split the preferences in this tab into multiple free standing preferences, since they are so closely related.

In reply to by Soerboe

<< Do you think this list should contain all preferences? I ask because some preferences require quite a lot special code just for a single preference >>

That's right.
If preferences are presented a la Firefox as proposed (which is a very good idea for me), then only boolean, integer and string choices would be available.
It is this simplicity which ensures that the list is updated by developers at each release and always contains the full list of possible change.
But it is also that which makes that some of these preferences must be changed by group of 2, 3 or more values in a coherent way by users otherwise the system can stop working properly.
This is why we get the message "This might void your warranty" when you enter the advanced preferences tab in Firefox.
A possibility for MuseScore could be to list all preferences that can't hurt in the advanced tab, and really all preferences including the ones that can hurt if the user click a check box with a warning?

In reply to by frfancha

Well, first of all I don't think a preference should "hurt" in the sense that the program will stop working correctly. If changing a preference breaks the program, then the preference should not be there.

When asking if the list should contain all preferences, I was thinking about the preferences already listed in the different tabs in the preference window. The preferences are grouped together for a reason to make it intuitive for the user. If all preferences are available free standing in a list, users will miss the connection between some preferences. I think...

In reply to by [DELETED] 5

I definitely support this idea - both the notion that we should have have more things configurable for those who want that kind of control, and the notion that it is better to not worry about a full blown GUI (which is a maintenance headache).

I would suggest though that we may want this for both application preferences and also for score style settings.

Am I on the right track? Is this close to what you were thinking about, @lasconic? See screenshot below (the preferences shown are just for testing)


In reply to by Soerboe

Cool start !
Again a la firefox. I would not make the left column in english. Instead I would something like audio.interface.api or ui.voice.1.color etc... Preferences around the same topic would then be listed together when the interface is sorted. So I believe the code for this feature should be minimal, it's more about reorganizing the preferences, give them meaningful key and have a way to loop through all them and display the right widget (color picker, boolean checkbox, text edit, combo box etc...) depending on the type of the preference. Hope it makes sense.

In reply to by [DELETED] 5

It makes perfect sense :)

However I wonder if a struct (which is now holding most of the preferences) is the right data structure? Is there a good reason to use a struct? I believe some sort of map/set with a string key for each preference is a better approach. Then for each preference a default value could be assigned and e.g. max/min allowed values.

What do you think?

PS: I find that some preferences are not in the preference struct. Is there a good reason for this? Example: Mscore::selectColor and MScore::warnPitchRange

In reply to by [DELETED] 5

Yes, the settings are stored in QSettings which handles storing the preferences to file. The code goes like this:

  • Read preferences from QSettings and store each preference as a member of a struct
  • While MuseScore is running the preferences struct is used to access and modify the preferences
  • Then the preferences are written to QSettings

My question is: Why use the struct as a kind of proxy for QSettings. Why not use QSettings directly to access and modify the preferences?

E.g. it is way easier to iterate QSettings than members of a struct...

In reply to by [DELETED] 5

As we talked about in IRC the preferences struct is not used in libmscore. However there are multiple variables defined in libmscore which have their value set in PreferencesDialog (e.g. MScore::defaultColor and MScore::bgColor in MScore class). These variables are used in libmscore and can not automatically be moved to mscore. Since the MScore class is defined in libmscore it can not use QSettings to retrieve values itself (as is the case in all classes in mscore folder).

Can you think of a solution to this issue?

If the handling of preferences is to be made more flexible and automatic such special cases must be ruled out.

In reply to by [DELETED] 5

Bad explanation on my part.

I was trying to think of a way to take away the responsibility of PreferenceDialog to update members in other classes. And rather let the classes itself listen to changes in preferences and update its members on their own. Personally I think this is a more robust way of dealing with preferences.

But maybe I'll start with a simpler approach first.

In reply to by Soerboe

Here's a case where the current way of doing things (i.e. PreferenceDialog updates members in other classes) doesn't work properly (at least not in 2.x): #270328: Changing default colour does not affect text

The problem occurs when PreferenceDialog updates a value in MScore (in this case defaultColor) but that value has already been used elsewhere by a class that does not get updated (in this case in text styles). The result is that lines and musical symbols change colour when defaultColor is changed in preferences (because they check MScore::defaultColor) whereas text styles do not (because they forever use the value that they were initialised with).

Perhaps there should be some level of indirection, so PreferenceDialog and other classes check/set shared pointers rather than shared values? That way classes can always get the latest value from the pointer, without having to be notified of any changes.

I now have the following preferences in the "advanced" tab (see screenshot):
Are there any of these preferences which should not be in this list?

Any other comments?

In reply to by Soerboe

Looks good to me.

I personally think that the "Advanced" tab should list all preferences, including those that can be set via the other tabs (perhaps it should be called "Other", "All" or "List" rather than "Advanced"). This has the advantage of:

  • all preferences configurable in one place
    • easier to tell users to search for the preference named "X" rather than hunt through all the different tabs
  • no preferences accidentally forgotten
    • if we decide to change which preferences are listed under the tabs then we might forget to update the "Advanced" list, so it is safest to have it so that all preferences automatically part of the "Advanced" list

The list is excellent from an accessibility point of view, so it may be worth adding a description of each preference and making the description searchable (and translatable). However, I wouldn't bother doing this for your initial implementation.

In reply to by shoogle

I second what shoogle says about advanced tab listing all preferences. Would such a list be populated by looking the preferences class itself, so that "no preferences accidentally forgotten" when some future code change adds a new preference?

In reply to by shoogle

If I remember correctly, Soerboe actually started out with all preferences, but after a bit of irc conversation we settled on listing the ones not present in another place for the first implementation.
Reason being that it turned out to be not so easy to keep them in synch between the tabs. You'd have to further rework the preferences into something observable and update all the existing tabs to respond to the changes of a preference.

In reply to by jeetee

I see, well feel free to do whatever is easiest for now. I supposes you might also have that problem with "playRepeats" and "workspace" if changing them in the Advanced preferences doesn't also change them in MuseScore's main window.

@Soerboe, do you have a PR on the go?

In reply to by shoogle

I would also liked to see that this list contained all preferences. However, as mentioned by jeetee this proved more difficult than I thought. There are quite some corner cases in prefsdialog which I didn't find a good solution for.

I have a PR ready soon.

@Soerboe are you still working on it?
I just added a "show all preferences" option, but before doing more (and making a PR), i'd like to know if we are both working on the same thing at the same time.

Do you still have an unanswered question? Please log in first to post your question.