PDA

View Full Version : Qt Application Preferences Best Practice



stefanadelbert
1st November 2011, 00:37
I'm busy creating a preferences dialog for my Qt application. The preference will just contain colour/theme settings for one of the widgets in my application which is used all over the place, i.e. many instance of the same widget at any one time. I would like to colour preferences to apply to each instance of the widget immediately when they are changed. I'm wondering how best to achieve this and if there is some accepted best practice for system wide preferences like this. I have a number of ideas for how to achieve this and they will probably all work, but some will definitely be messier than others.

One idea is to have a ColourManager widget which emits colourChanged(EColour, QColor) where EColour is some enum, e.g.

enum EColour {
COLOUR_SPECIAL_HIGHLIGHT_1 = 0,
COLOUR_SPECIAL_HIGHLIGHT_2,
COLOUR_ERROR_FOREGROUND,
...
}

As long as that signal gets to each widget that cares about colours then they could update their internal states accordingly and paint themselves with the correct colours.

The next question would be how best to hook up the colourChanged(EColour, QColor) with each widget that's interested in colours. I imagine that the QMainWindow would own the ColourManager and would also each of the widgets that might be interested in colours. So QMainWindow could connect the colourChanged signal to the relevant ColourChanged slots.

I am aware of QSettings and make use of it to store various application settings already. Another idea would be to write colour changes to QSettings and then have other widgets read settings from QSettings.

If you've tackled this before or have any ideas, please let me know.

Thanks
Stefan

Santosh Reddy
1st November 2011, 01:00
I suggest using Qt Style Sheets, or setting the QPalette of the widget.

IMHO "enum EColour{...}" may not be a good idea.

stefanadelbert
1st November 2011, 05:16
Thanks for the reply, Santosh.

I already use stylesheets for other aspects of the application's theme. But what I need to be able to control are the background colours of cells in a QTableView (the background colour depends on the content of the cell). I'm currently doing this in the underlying model using Qt::BackgroundRole and returning hardcoded colours. I would rather be able to pass back colours that could be customized globally by the user and persisted from one instance of the application to the next.

Given that it's up to the model to decide which background colour to use based on the cell's content and I don't think using a stylesheet to achieve this isn't feasible in my opinion (I had thought about it though).

I looked into QPalette, but it seems specifically designed to deal with the colours for GUI widgets. If I could add custom colour roles then I might be able to reuse QPalette, but that doesn't seem possible.

I've just had a look at KDevelop's config dialog and it allows the changing of certain colours that are then applied globally and are saved for the next time KDevelop is run. This is more or less what I'm trying to achieve. I tried to have a look at the source, but it was taking me ages to find the relevant code, so I gave up!

Santosh Reddy
1st November 2011, 05:55
I believe the global change of colors is achieved using QPalette like approach, I am afraid you may have to consider using either QPalette as is or write a similar class with custom color roles as per you needs. But again this is same as your initial idea of having a ColorManager Widget. You can have two classes, one as custom color palette, and other as a widget which can edit this custom color palette (like using a color picker). You can set this custom color palette on the model directly, and model can be implemented to used the custom color palette color roles. As you already considered QSettings, it is simple and nice ways make these settings persistent.

FYI, I ran into similar task some time back, I ended up writing a small class. It was not just color though, it had other application wide configurations like fonts, font size, buffer sizes, timing etc.

If it is just color you are looking for, and if is just the Qt::BackgroundRole you are supplying to View, then I would still go with QPalette. Writing a custom color palette may not be of much use as the View does not understand these custom color roles, unless you implement a custom view which I guess you are not doing.

anyways see if someone has any ideas.

stefanadelbert
1st November 2011, 06:36
I suppose that what I put in place now will be the beginning of the preferences for the whole application. Ultimately I would like to be able to support customisation and persistence of colours for certain parts of the GUI and fonts, the actual fonts themselves, sounds used, etc. So I would like to get it right from the beginning to avoid too much refactoring down the line.

I had the idea of having a custom QObject class similar to QPalette, CCustomPalette, with a number of roles that are particular to my application. I could then have a widget that could submit colours by colour role to CCustomPalette, using QColorDialog as you suggest. CCustomPalette could emit colourChanged for each colour that is submitted as is different. Then each model in my app could have a CCustomPalette that would act as a cache and listen out for colourChanged from the central CCustomPalette and handle it with the ChangeColour slot.

One tricky thing will be organising how to connect the colourChanged signal of the central CCustomPalette to the ChangeColour slot of the "satellite" CCustomPalettes.

Santosh Reddy
1st November 2011, 06:47
You could use a CCustomPalette factory, where all the required signal & slot connections are made, but this could be still tricky as you said, as you also need to update all the views (if visible) which use the models using CCostomPalette.