The function QEvent::registerEventType() finds an un-created event type (between 1000 and 65535) and I believe it returns the first one it sees. How does this work, when it has to dynamically update enum Type in order to account for the new event?
Is an array involved to track the unregistered events?
Also, when you allocate an event, does it add it to the QEvent::Type enum list?
Are there any ideas on how this function works?
Sure, sure. But the question is, I think, how do you use this generated unique id? The problem seems to be that QEvent doesn't take an integer, but a QEvent::Type enum in the constructor, and QEvent::type() returns a QEvent::Type. So, what do you actually do with your shiney new generated id? How do you use it to distinguish your event from other event types? Or can you just ignore the QEvent::Type and treat it as an int?
In the link, I didn't really understand what the userEventRegistrationHelper() function did, and I didn't see a definition for it, but that's a different problem.
What I did see was that it loops through all possible custom event enum values (65535 all the way to 1000), and uses these member functions/variables of userEventRegistrationHelper (which also seems to be an instance).
Andre, I think I saw an "example on StackOverflow":http://stackoverflow.com/a/4269757/1276964 (it uses a cheesy typecast from an int to an enum) that helps me understand the problem.
My main question is how Qt tracks an enum to find un-registered enum numbers and if I can have my event be part of QEvent::Type enum.
This is all just curiosity, I'm just a hobbyist.
userEventRegistrationHelper() is a static function returning a global "QEventUserEventRegistration":http://qt.gitorious.org/qt/qt/blobs/4.8/src/corelib/kernel/qcoreevent.cpp#line355 instance (in a lazy-loaded, thread-safe manner due to Q_GLOBAL_STATIC).
I thought the easiest way to answer your question is to link to the correspoding code, because it is the most obvious explaination: If the desired type (hint) is valid and not in the list of already taken types (userEventRegistration.set), take it. Otherwise find a non-taken type by iterating from the maximum value (QEvent::MaxUser) to the minimum value (QEvent::User), which is not in the list of already taken types.
[quote author="Flurite" date="1348864532"]...how Qt tracks an enum to find un-registered enum numbers...[/quote]Qt keeps track of all registered user event types in a global list (userEventRegistrationHelper()->set), which is used in QEvent::registerEventType() to determine an unused event type.
[quote author="Flurite" date="1348864532"]...and if I can have my event be part of QEvent::Type enum.[/quote]No, you can't, at least not without modifying the Type enum found in the qcoreevent.h header (no QEvent::Type type = QEvent::MyEventType).
However, you can store any arbitrary value of the enum's underlying datatype (which can be any integral type, usually int) using an explicit static cast (QEvent::Type type = static_castQEvent::Type(42)), as show in the SO example.
[quote author="Andre" date="1348832220"]Sure, sure. But the question is, I think, how do you use this generated unique id? The problem seems to be that QEvent doesn't take an integer, but a QEvent::Type enum in the constructor, and QEvent::type() returns a QEvent::Type. So, what do you actually do with your shiney new generated id? How do you use it to distinguish your event from other event types? Or can you just ignore the QEvent::Type and treat it as an int?[/quote]
I usually follow this pattern:
- every QEvent custom class has a static member variable, typed int, to hold the registered event type
- in main() I initialize all those variables using registerEventType
- in their constructors I call the base-class constructor with QEvent(static_castQEvent::Type(id)), plus a Q_ASSERT(id != 0) to be 100% sure I don't miss an initialization and leave the value zero-initialized
So I conclude, that QEvent::id() and QEvent::QEvent(<type> id>) should have been int based, and not use QEvent::Type as the type. It is weird that you need static casts to and from an enum to hack in values that don't really belong inside the enum in there anyway. Thanks!
Well, I think it is a classical trade-off.
You will have to use a static cast anyways, either when using a custom type in the case of QEvent::Type or using a built-in type in the case of int, as there is no implicit conversion from int to QEvent::Type.
On the supposition that in the majority of cases you will use a built-in type using QEvent::Type will leave you with a static cast in the minority of cases (instead of the other way round).
You can add a QEvent::QEvent(int) constructor, which will act as an implicit conversion constructor, but you will nullify the reason then why you've used an enum in the first place: type safety - which is of course quite debatable as QEvent is meant to take types not beeing part of QEvent::Type anyways ;-)
Interestingly enough QEvent itself uses an integer to store the type (more precisely ushort) internally, so there might be other reasons for having an QEvent::Type based interface.
Well, you can directly compare an int against an enum value, right? You don't need static casts for that, AFAIK. Enums are used not only for type savety, they are also convenient containers for a set of const values. That is done all over Qt already. And as you say: QEvent already takes values not in that enum, and is obviously designed this way too. So, I think int would have been a better choice.
[quote author="Andre" date="1349089282"]Well, you can directly compare an int against an enum value, right? You don't need static casts for that, AFAIK.[/quote]Yes, you can, because there is an implicit cast from enum to int - but not from int to enum.
-So the problem would not be merely the comparison, but rather instantiation. Having an int based interface would mean that <code>QEvent(QEvent::WhateverEvent)</code> would become <code>QEvent(static_castQEvent::Type(QEvent::WhateverEvent))</code>, as used hundreds of times in Qt itself - this isn't a viable option.-
-So the only thing I see happening is having both, a QEvent::Type and int constructor.-
No, it would not need a cast there, as as you say enum to int is automatic. So if it would have been QEvent::QEvent(int), then QEvent(QEvent::WhateverEvent) would have worked just fine. Only the other way around needs the cast, as we've already seen.
I am not saying that I will see this change happening, I was just arguing that the current API is a bit strange if you want it to be extendible by 3rd party code defining custom events, as is obviously the case.
Well, of course there would be. Sometimes you are just beaten by your own logic. ;-)