Preface: In my new series “Say hello to…”, I regularly present you additions to my Git-based collection of useful helper classes and smaller projects (see its very simple homepage for more information).


Yesterday, you saw me debugging models. Today, you see the result: I’ve implemented a model that lists other models.

The ModelListModel in action

The ModelListModel in action

Perhaps you find this useful for your own application (I’ll use it for fantastic new features in Palapeli’s puzzle library). In an ideal world, I would have implemented a yet more generic model, in which one can “mount” other models at arbitrary positions, but from what I know about model/view programming, this is very hard to do right (i.e., without massive memleaks).

Advertisements

Preface: In my new series “Say hello to…”, I regularly present you additions to my Git-based collection of useful helper classes and smaller projects (see its very simple homepage for more information).


Today, I needed a dialog for Kolf that shows a list view to the user, and lets him select some items from that (plus the “OK/Cancel” buttons which you’re used to from modal dialogs). I had to create a new class, complete with own header and source file, because I needed to declare a new KDialog subclass with a slot.

Incidentally, I’ve already created such dialogs for Palapeli. And much of them. So this is a task that should clearly be simplified. This is how the SelectionDialog class came into life. See the APIDOX in its header for details on how to use it.

Say hello to StaticVector!

September 20, 2009

I present you the second addition to my Git-based collection of smaller code pieces (which now also has a very simple homepage).

This time, I show you a generic container class. There is already a big bunch of container classes in Qt, but I had to make one that fits my needs: the StaticVector.

Its API and purpose is similar to QVector, but it behaves quite differently: A StaticVector does never reallocate or resize its data unless it’s explicity told to do so. Also, any copy of a StaticVector will be read-only, because the data is implicitly shared for performance reasons, but write operations would require the copy to detach from the original data (which is an implicit reallocation, which is forbidden).

The usecase for this is quite simple: In Kolf, we are regularly passing big data arrays to OpenGL and ODE. And passing big arrays to methods from C libraries almost always requires one to pass a base pointer and a size, i.e., two parameters. With such data encapsuled into classes (such as QImage), you might end up with a situation like the following:


void passData(uint* data, int size);

class MyContainer
{
QVector m_payload;
public:
QVector payload() const { return m_data; }
//...
};

MyContainer container;
//...
passData(container.payload().data(), container.payload().size());

This is asking for trouble. The two calls to MyContainer::payload() in the last line create two temporary objects. The latter one is not problematic, because QVector::size() is a const method, but QVector::data() is a non-const method (because the C library wants a modifiable pointer). Calling it causes this temporary QVector instance to detach from the original payload, i.e., allocate new memory and copy the data to there. The C library will remember the pointer to this newly allocated data. After the passData method call, the temporary QVector instances are deleted, which causes the newly allocated data to be deallocated. When the C library tries to access this data later on, we’ll get a SIGSEGV or even uglier things.

That’s where StaticVector comes in. If you substitute QVector with StaticVector in the above example, everything works well, because the temporary StaticVector instances are read-only, but (for this usecase) may return a non-const raw data pointer.

If you ever need to use C libraries which want non-const data pointers, StaticVector might be a good choice for you, because it allows to get this non-const pointer even from const or read-only StaticVector instances, while it minimises misuse of this pointer as much as possible.

Say hello to QRangeSelector!

September 12, 2009

As suggested yesterday, I’ve set up a Git repository for “a broad collection of smaller code pieces which I’ve acquired over the course of my life”. Find it at http://github.com/majewsky/majewsky-misc/, and clone it from git://github.com/majewsky/majewsky-misc.git.

As some first entry, I actually put some stuff I’m currently working on. In line with Andreas Marschke writing about his recent work on a generic video widget, I’m announcing QRangeSelector. This class is similar to a normal slider, but it does not only allow to select a single value, but to select a range of values from some bigger range. (One may also, given some big range, select a small range from it, and select a value within this range.) QRangeSelector also allows for arbitrary contents to be drawn inside its slider area. This screenshot illustrates some usecases which I need in Kolf. (If you do not see the benefit yet, I’ll do a screencast once the QRangeSelector is used in Kolf.)

Testcase for QRangeSelector widget

Testcase for QRangeSelector widget

Note: The white widgets at the top and inbetween the two QRangeSelectors are simple line edits. I needed those to test keyboard focus.