Tuesday, July 13, 2004

A small bug in almost every KDE app...

My favorite features of KConfigXT is that when you open an app that uses KConfigXT it won't dump any settings to your home directory unless you change them to something other than the default value. This same feature has been incorporated into the KMainWindow class (among others) with the window size. If you open an app and close it without changing its size it wont save the size as it is the default. At least that is what it should do.

Looking through my .kde/share/config/ directory this evening I noticed that the applications that used kconfig that I simply had opened to look were empty except the default window size of the app, something that shouldn't have been there. A quick look at kmainwindow I found that it did remove the entry if what it thought was default was the final size on exit. So what was going wrong.... Turned out that what it read as the initial size was in fact not the default. I began looking at the applications that had this problem and right off the bat found a reason for this problem.

Most of the time the problem revolved around applications that had hard coded sizes. The simplest problem was when apps called resize() after setAutoSaveSettings() or setupGUI() (setupGUI() calls setAutoSaveSettings() ). setAutoSaveSettings() when called will load the last saved size, and if an applications calls resize() right after that, then users will never see the size saved. If the resize() was before the function calls there was problems too. If I had a theme that was larger then what the developer used or larger default fonts or the size was simply from when the app was smaller or if kde ever moves to a different size default toolbar having resize before those two function will cause a problem as the initial size wouldn't be the default size presented to the user. So simply removing resize should solve the problem right?

Removing hard coded anything is good and what should happen is the size will be determined by the widget re-sizeing itself when the widget is shown. In all the cases I have run across setupGUI() is called before show() and thus nothing has automatically been resized yet. To fix this setupGUI() will now check and to see if the widget hasn't been shown and call adjustSize() to fix this. All done right?

If setupGUI() is called before setCentralWidget() than adjustSize() won't be applied to the main widget and the "default" size will be wrong.Ok so now that apps don't hard code the size and everything is created before setAutoSaveSettings() is called so the default size is correct right?

Apps that have widgets that inherit from QWidgets like in most games often times didn't impliment sizeHint. The default sizeHint of QWidget I think is 0x0 which is not what we want for the default size of the main widget. So for those widgets the sizeHint() function needs to be added.

And finally after all that, KMainWindow now has the proper value for the defaultSize when setAutoSaveSettings() is called. What started out as a simple fix for ktron ended up uncoverting a lot of small issues all over in many different apps. Beyond the original goal, migrating the apps to automatically determine their default size is much more elegant than the mired of different solutions that apps had implemented.

Some guildlines when fixing apps:
  • Remove hard coded resize() calls in the constructor or main, they should be removed in favor of letting the automatic resizing determine the default window size.
  • Put the setupGUI() call after all widgets have been created and placed inside the main window (i.e. for 99% of apps setCentralWidget())
  • Widgets that inherit from QWidget (like game boards) should overload "virtual QSize sizeHint() const;" to specify a default size.

Finally to test to make sure it is working; simply delete the applications config file, launch the app, exit it, and if the config file exists it shouldn't contain the width/height entries if everything is working.

Popular Posts