Tuesday, April 21, 2015

QMessageBox with a countdown

Ever wanted a QMessageBox that includes a countdown and executes a default action in case the countdown is expired and the user has not done anything? The following is wrapping this functionality in a small subclass.

Thursday, April 16, 2015

Uncheck all buttons of QButtonGroup

Uncheck all buttons in QButtonGroup


A QButtonGroup can be nice e.g. when you have a set of checkable buttons where only one of them should be checked at any given time. You simply add all the button to the button group and set it to be exclusive and everything else will be handled automagically.
However, sometimes it is necessary to be able to uncheck a button (and therefore all the buttons) of a QButtonGroup, which is unfortunately not directly supported. To work around this limitation you need to disable the exclusive property of the button group before unchecking the button and enable it afterwards again.

You can also use this little class, which hides the boilerplate code behind an uncheckButtons() function:

Friday, June 7, 2013

Qt enum to string / string to enum / flag to string / string to flag

Was recently changing the way one of my application stored values in it's configuration. Entries that were presented to the user via QComboBoxes were stored by index in the configuration, which made it impossible to understand the configuration without having the application running next to it.
I came up with a couple of macros, utilizing QMetaObject / QMetaEnum. The QMetaEnum class provides functionalities to translate an enum or flag value into a string and vice versa. The problem is that the way of achieving this would involve syntax like

auto metaObject = ObjectName::staticMetaObject();

auto enumIndex = metaObject.indexOfEnumerator("MyFencyEnum");

auto metaEnum = metaObject.enumerator(enumIndex);

auto enumString = metaEnum.valueToKey(MyFencyEnum::EnumVal1);

OR

auto enumValue = metaEnum.keyToValue("EnumVal1");


Thus, I`ve created the following macros that make the code a whole lot cleaner:

// c = class name; e = enum name; v = enum value
#define ENUM_TO_STRING(c, e, v) \
    (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(#e)).valueToKey(v))
// c = class name; e = enum name; s = string value
#define STRING_TO_ENUM(c, e, s) \
    (c::e)(c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(#e)).keyToValue(s.toAscii()))
// c = class name; f = flag name, v = flag value
#define FLAG_TO_STRING(c, f, v) \
    (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(#f)).valueToKeys(v))
// c = class name; f = flag name; s = string value
#define STRING_TO_FLAG(c, f, s) \
    (c::f)(c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(#f)).keysToValue(s.toAscii()))

And here is another useful macro, helping to get the number of values in an enum:
//c = class name; e = enum name
#define ENUM_KEY_COUNT(c,e) \
    (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(#e)).keyCount())

Maybe someone out there can also utilize these.

Monday, November 26, 2012

QDataWidgetMapper and QComboBox

Just came across a small drawback, when using QDataWidgetMapper and trying to add a mapping to a QComboBox. Unfortunately, QComboBox implements the USER property like this:

 Q_PROPERTY(QString currentText READ currentText USER true)  

Since it only declares the READ function, this means that it is not possible to e.g. use a QDataWidgetMapper and a QComboBox to sync contents to a model. One workaround would be to subclass QComboBox and implement a WRITE and NOTIFY function as shown below.