Taschenorakel.de

Postings tagged with Miniature

Miniature 0.5 'London 1851' released

From the release notes: "Miniature now supports different languages thanks to a determined community of translators. Thank you for your effort! This is why we are dedicating this release to the first international chess tournament, celebrated in London on 1851.

Miniature 0.5 is being released for MeeGo Harmattan (Nokia N9 & N950) and Maemo (Nokia N900). Thanks to everybody involved in the initial Maemo attempts and the experimental version that was made available after the Miniature 0.4 release."

We also improved usability, compared to the previous release, but there's still a ton of work left.

A bit of history

I started working on Miniature – a chess client for freechess.org – in November 2009, after reading the Call for Contributors. Even though we had a pretty cool P2P feature (based on Telepathy and developed mostly by Dariusz Mikulski), it never quite reached the original goal: playing chess online. Back then I was learning how to create UI's with Qt Graphics View, which was all the rage at the time. Well, we now know that writing real UI's with that technology is a major PITA, but for my pet project, it was just too much. I got lost in the struggle.

For the next 18 months, Miniature was basically dead. Another failed project that started so promising. Quim did not want to give up though. After the N9 announcement, he launched a second Call for Contributors.

Perhaps I responded to his mail because I was embarrased at the idea of people wasting time trying to salvage the working parts of Miniature; there simply wasn't much to salvage! So I started again, this time with a very clear goal: online chess, and online chess only. Let others create the actual UI and whatnot. Focusing on one prominent feature and not having to worry about the UI worked well for me, even though I had to iterate over some architecture ideas until I felt comfortable. Quim in the meantime started to prototype the UI with QML. It was impressive to see his results, a level of polish I could have never achieved with my Qt Graphics View approach. At some point the backend was good enough to be sewn together with the frontend and suddenly we had achieved where I failed before: A touch enabled chess client for the N9 that can play chess online.

Having my own useful application available on the N9, published through OVI store, means a lot to me. I hope others will enjoy Miniature as much as we enjoyed re-creating it the second time around.

Miniature goes Telepathy

Thanks to the work of Dariusz and Alban we now have P2P via Telepathy for Miniature.

Maybe it's worth to notice that we use Maemo's contact chooser here, and that it blends perfectly with our Qt application (we still have some crashes on our side though). Nice job from the Fremantle team! there!

Logging facility for Miniature

On Maemo 5, log output from your app isn't always accessible to the user. This has created problems for Miniature bug reports (see bug #8124). To solve this, I created a "Game Log" screen which allows to filter the messages (by a given log level, I might want to allow combinations, too). It also has a nice fat "Copy all" button, so that the log output can be quickly attached to a bug report.

Now I "only" need to add useful log information =D

Thanks to Openismus for letting me work on this.

Fragile API and invalid iterators

For the Miniature project I sometimes need to iterate over all graphics items in a QGraphicsScene, or more precisely, all items of a specific parent item, the chess board itself. For that, I use the QGraphicsItem::childItems() API. However, when used with STL-style iterators you have to be careful, since value types of that form can easily break the iterator idiom:

for (QList<QGraphicsItem *>::iterator iter = parent_item->childItems().begin();
     iter != parent_item->childItems().end();
     ++iter)
{
    (*iter)->doSth(); // Ooops! Invalid iterator deref'ing! 
}

The value-type list that is returned by parent_item->childItems() has not been bound to a variable explicitly, so it is bound to an anonymous variable instead. The compiler will not complain here although the code is borken, from a C++ point of view. Worse yet, "(*iter)->doSth();" might work often enough for you to not see the crashes right away, depending on the compiled code and how the architecture handles memory.

Eventually though it will crash, and according to Murphy this will happen right after the big release. Valgrind of course would have complained about the illegal memory access right away (when run through that part of your code), because the list that we queried in the loop header is invalidated as soon as we enter the loop body, leaving us with an iterator that points into the void. This is C++-specific, in other languages even anonymous variables are only ever cleaned up after leaving the current block context, but in C++ their life time is only guaranteed for the scope of the current expression.

There is one fix and one workaround to that problem. First the fix: let QGraphicsItem::childItems() return a reference to a list member instead, or simply expose the begin/end iterators for the internal data structure directly. Assuming this is not possible, we are left with the workaround - bind the returned list to a variable explicitly, before the iterator is used:

QList<QGraphicsItem *> children = parent_item->childItems();
for (QList<QGraphicsItem *>::iterator iter = children.begin();
     iter != children.end();
     ++iter)
{
    (*iter)->doSth(); // Fine!
}

This of course prolongs the life time of the returned list unnecessarily. We only needed it inside the loop, but now it won't be cleaned up until the flow of control leaves the surrounding block context. To finally get the desired behaviour we could limit the surrounding block context:

{
    QList<QGraphicsItem *> children = parent_item->childItems();
    for (QList<QGraphicsItem *>::iterator iter = children.begin();
         iter != children.end();
         ++iter)
    {
        (*iter)->doSth(); // Fine!
    }
}

Perhaps a cleaner way is to move the loop code in a function of its own instead, although that might not always be feasible, depending on the code inside the loop body.

Another issue might be the need to dynamically cast QGraphicsItems (QGI) to the desired type, once you implemented your custom QGraphicsItem type. This wouldn't be too bad if there wasn't this horrible mix of QGraphicsObjects and QGraphicsItems in Qt 4.6 - some items inherit from QObject (QGraphicsSvgItem), others don't (QGraphicsPixmapItem). So now you also have to decide between dynamic_casts and qobject_casts, how nice ... not! Honestly, it would be easier here to simply forget about qobject_casts, but that might break in subtle ways.

These two issues were enough for me to avoid the QGI::childItems() API whenever possible. One possible replacement can be provided by signals and slots [1]: First, add a slot representing the loop body to your custom QGI type. Second, connect a signal to the instances of your QGI type that would have been iterated in the loop, that is, have a custom signal representing the loop iteration. Then, instead of iterating over the children of the parent item you simply emit the custom signal which triggers the "loop body" execution for each connected custom QGI instance.

[1] requires QObject inheritance for your custom QGraphicsItem type

First Miniature .debs sighted!

Thanks to Mathias, Miniature is now suitable for debian packaging. He also uploaded a first test balloon which at least allows you to move pieces around. Feedback is of course more than welcome.

Personally I wish the board's cell size could have been made bigger, but 60x60 pixels is already the upper limit. It is now up to us - the Miniature team - to come up with clever techniques to make the board handling as finger-friendly as possible.

Qt 4.6 for Maemo: It works!

Today at work, David King kindly informed me that there was some new Qt package in extras-devel. This could only mean one thing - I immediately fired up my scratchbox environment and installed the packages, trying to confirm that this new version would run with Qlom. And in fact, it was surprisingly painless. Thanks to autotroll, a simple QT_PATH env variable did all the magic, hooray!

Both of us were impressed with the UI improvements. It's certainly a big step forward regarding the Hildonisation of Qt on Maemo5. The application menues look correct now. Button sizes, colors, animations, etc - it all comes together nicely, finally.

There are still some widgets that need more work, but for a tech preview this is a pleasant surprise.

Miniature

On another note, the timing for the Miniature project could not have been much better. We immediately switched to Qt 4.6, and it even runs on the N900. It feels good to know that we can stop using hacks and that we can start to do (most) things properly, staying as cross-platform as possible. Needless to say, Quim was happy, too.