Qt 4: Disabling a Bunch of Widgets

I just had a problem with Knowledge, which as you might know, is my attempt towards a Wikipdia offline reader: I needed to disable lots of GUI stuff in my QMainWindow-derived class as long as no offline image is loaded. Some of the widgets werent even available as object members. All widgets need to be deactivated and then activated again after the book was loaded. The obvious choice would have been to add a bunch of members, one for every object in question, and then call setEnabled( true ) or setEnabled( false ) for each of them respectively. Result: lotsa code. Lotsa members, sucks.

So what was my solution? Obviously, all relevant classes in this case are really QWidgets (except for QActions, I'll get to them later). So what I did is having a private member QList < QWidget* > mStateWidgetList. Every time a widget shows up I would add it to the list. Tackeling a bunch of them is just as easy:

mStateWidgetList << firstWidget << secondWidget << ... ;

At the end of the constructor I call

foreach( QWidget *w, mStateWidgetList )
w->setEnabled( false );

And the same with "true" as argument at the place where stuff a book gets loaded. Very simple, looks clean and no need for ugly global pointers just for the purpose toggeling the enabled-state. The performance penalty due to dynamic nature of this solution shouldn't be too bad either.

The only obvious downside of this approach of cource is that it won't work with QActions, which can also be enabled or disabled. You'd need to special-case those, qobject_cast attempts are your friend here. In this case, this should be a nice enough task for a little helper class. I just think it rocks. Now I am waiting for someone to tell me how he had the same idea back in 1998 :).


this could be very handy especially if you have your widgets in "groups" via the lists. Then you can basicly have a method that will batch enable/disable them. either way, pretty cool

By Ian Reinhart Geiser at Mon, 05/02/2005 - 00:06

I'm not entirely clear on your problem; but doesn't the top-level widget (MainWindow) contain a list of widgets already?
I'm pretty sure that Qt has lists of all children for each widget already which you can then use like you use your own list. Maybe add a check for a class-type (dynamic casts) is needed to only disable your specific widgets.

By Thomas Zander at Mon, 05/02/2005 - 09:17

Yes, sure I could. The point is that the widgets are spread across the whole mainwindow and I don't know which ones, so I need to keep a list anyway. If it several widgets that are grouped together anyway, I would probably place them inside a QFrame without margins and disable the frame, which in turn disables the frames children :)

By Daniel Molkentin at Mon, 05/02/2005 - 09:56

Simon actually had a much better idea than messing with qobject_cast: Exploiting properties, which are all runtime-checked. This suddenly turns into an advantage here. The declaration is now:

QList mEnableList;

and the code reads like:

mEnableList << firstWidget << anAction << secondWidget;

foreach( QObject*w, mEnableList )
w->setProperty( "enabled", false );

And it works perfectly for both QActions and QWidgets. For everything else, you will see a qWarning.

By Daniel Molkentin at Mon, 05/02/2005 - 10:03