Blog

Impressions from Minecraft

Before I get to the point, just a few updates. I just finished refreshing the components available on this website, so now they're finally all up to date. I also published some recent photos of Adam. He's growing and changing so quickly that it's hard to keep up :). Last but not least, I released version 1.0.2 of WebIssues some time ago with some minor fixes and improvements.

Why do I write about Minecraft? It's simply impossible to avoid it. I had a short adventure with the free Classic version in January, when Adam was still at the hospital. I knew I shouldn't even think about the full version, because I'd be stuck with it for a long time. I managed to forget about it until recently I bought May Payne III and I was looking for an online review. Then I accidentally found that an Xbox version of Minecraft is available. I didn't even finish playing Max Payne (which is great, by the way, almost as much as the original version was 12 years ago) and bought Minecraft. It's not hard to guess that it costed me a few nights with hardly any sleep.

I think that there are already a few dissertations about the Minecraft phenomena. A world made of blocks that you can freely dig and move around is simply every geek's dream. Games like Max Payne have great graphics and action, but it's sometimes annoying that you can't just get off the linear path and venture into the Sao Paulo favelas. Games like GTA don't solve the problem - you can go anywhere you want, but there's not much interaction with the world other than shooting people and running them over. In Minecraft there are no limits. You are a god in a digital world. Add to it a few zombies and retro style graphics and you have a recipe for success.

The Xbox version of Minecraft is still quite bit behind the PC version. It lacks enchanting, potions, a lot of biomes (there is only forest and desert, at least in my world) and structures like villages and strongholds. Hopefully they will add these features soon, but even as it is now, it's a lot of fun to play. The size of the world is limited to 1024x1024 blocks, but it's more than enough for a single player or even a few players. It took me quite a while to travel around the entire world using a boat. Also there is still a lot of bugs. It happened to me once that after saving the game deep underground and loading it again, I was moved to the surface, surrounded by three creepers. It was quite annoying :).

I could just as well buy the PC version, but I like to separate playing from working, so I prefer not to have any games on my laptop :). Not to mention the effect of having a big screen and surround sound. Mouse and keyboard is probably more comfortable for this type of game, but you can get used to the pad. At the moment I'm a little bit burnt out, and I can definitely use a break. Fortunately in a few days we're going to Germany to visit my wife's sister. Besides the Euro Championship is more important at the moment :). But Minecraft is definitely the kind of game that you want to keep returning to, especially when new updates will be released. Keep up the good work, Mojang!

Filed under: Blog
Tags: personal

Simple XML-based UI builder for Qt4

Introduction

This library provides a tool strip widget, replacing classic menu bar and toolbars, and facilities for defining and merging the layout of actions from multiple components, using simple XML files.

Tool strips have several advantages over traditional menu bar and toolbars. Unlike menus, all most commonly used actions can remain accessible with a single mouse click, while it is still possible to put less commonly used actions in popup menus attached to tool buttons. On the other hand, actions can be logically grouped and visually distinguished much better than in a traditional toolbar, which is simply a long row of similar looking icons.

The XmlUi library also provides a set of classes which simplify building the tool strip and popup menus. The layout can be defined using XML files which allows changing them easily without modifying the code. They also allow the layout of actions to be merged from multiple components, which is most useful in applications which embed various types of views or custom plug-ins.

The first version of XmlUi was inspired by the KXMLGUI classes from the KDE libraries. Later the tool strip widget was added and a simplified version of the Windows Modern Style was incorporated to provide a better look and feel for tool strips and menus. If you prefer to use traditional menu bar and toolbars, you can use the older version of XmlUi.

Documentation

You can find the full documentation for this article at doc.mimec.org/articles/xmlui/. It is also included in the source package.

History

2.1 (2012-05-28)

  • fixed toolstrip appearance on Mac OS X
  • added the execMenu() and toolStrip() helper functions
  • display shortcut of default menu item in button's tooltip when available

2.0 (2011-12-19)

  • added the new toolstrip control
  • integrated the modern Windows style

1.1 (2009-11-23)

  • added: support for toolbar buttons with menus
  • added: styling splitters in main windows
  • fixed: improved appearance of styled tab widgets
  • fixed: painting undocked toolbars

1.0 (2008-06-23)

  • initial version

Downloads

This code can be freely used and modified in both open source applications (including GPL) and commercial applications. If you find it useful, please consider donating to mimec.org!

See also:
  • list of all XmlUi releases on the SourceForge.net download page
  • accessing the current development version directly from the WebIssues source repository
Filed under: Blog

Reflections from POP diaries

Recently I came across Jordan Mechner's blog and the news that he just found the original source code of Prince of Persia on some old floppy disks after being lost for 22 years. That made me think about the time when I first played POP; I was no more than 10 years old and it was one of the first computer games I've seen. It was about that time when I started thinking that computers are fun and that I want to learn programming and create games myself.

I wonder if I also still have some floppy disks from Amiga 500 (and later Amiga 1200) hidden somewhere, with old pieces of code written by me. The oldest program that I wrote which survived to this day is called Polyglot. I wrote it in 1997 (being 15 years old) under the nick name "CompLex". It is still available in the Aminet archives, although only in binary form. I no longer have the source code. Maybe it still exists on the hard drive which I damaged many years ago by screwing it with too long screws which caused a short-circuit :). The oldest source code which I still have is Grape3D, written almost 12 years ago. It's almost completely unreadable, with lots of bitwise operations, pointer math, abbreviated variable names and literally zero comments, but it remains a really ingenious work of art that would be hard for me to match today.

I also read Jordan's diaries from making POP in late 80s and early 90s. It's really interesting and also quite inspiring. It also reminded me that I kept a diary between 1999 and 2007. It was mostly dedicated to various frustrations caused by my social life (or the lack of it), girls (or the inability to meet any), and general uncertainty of what I should do and what awaits me in the future. There are few mentions about the programs that I were writing at that time, because I deliberately avoided that topic. Anyway, from the perspective of a decade, life doesn't seem as bad as it used to, but it's definitely not getting any easier. It's just running much faster.

Jordan wrote a lot about his dilemma whether to write computer games or movie scripts. It's quite similar to the problem I currently have, trying to reconcile writing open source programs and the novel that I'm working on. I guess that's just the problem of people that are too creative :). There are a few major differences, though: Jordan had royalties from Karateka, and I need a full time job for living and for paying my loans; he was 21 when he started and I already turned 30 and have a wife and a kid to look after. So I'm not in a great position to disappear for half a year and write a bestseller book, or to invest in starting my own software company.

I really can't complain about my job, but I can't imagine working as an "outsourced" developer for the rest of my life, and being paid by the hour and not by the actual value of what I create. This is actually kind of frustrating and counter-productive, because the better and more efficient I work, the less I get paid for it. There are some ideas on the horizon how to change, or at least improve this situation. Perhaps I will finally be able to make some profit from the countless hours I spent on WebIssues. But so far, the only way I can do something to make me feel more accomplished is to pull all-nighters. I'm even doing it now writing this post. That's also not something I want to do for the rest of my life. Living from WebIssues royalties, travelling and writing books sounds much better.

Another lesson from Jordan's diaries is that even if you do a great job, there are still many things that may go wrong. Poor marketing decisions almost sank Prince of Persia, even though it was getting excellent reviews. I fear the same may happen to the commercial version of WebIssues. I know the value of this project; it can successfully compete with other applications, and the competition in this sector of the market, both open source and commercial, is very strong. But being able to make a profit from it is a completely different story. Of course, the only way to find out is to take the chance, and I will do it, but until I see some serious action going on, I will remain moderately enthusiastic about it.

Oh, and by the way, a new version of WebIssues is coming out probably next week. I'm just waiting for one Mac related bug to be fixed. And in the meantime I'm making some last minute improvements.

Filed under: Blog

Extensible SQLite driver for Qt4

This library is an alternative SQLite driver for Qt4 which includes its own copy of SQLite and allows extending it by implementing custom functions, collations, etc. It is very similar to the standard SQLITE driver which is part of the Qt framework.

The main difference is that upon opening a database, it registers custom collations for case-insenitive comparisions and a function implementing the REGEXP operator. These are the most important two feature missing from standard SQLite implementation.

Why create another driver and not just use the existing one? The reason is that it is currently not possible to call the sqlite_ functions from the SQLite API, because they are not exported when the SQLite library bundled with Qt is used. Unfortunately, this is the case for many platforms, including Windows. See QTBUG-18084 and www.mimec.org/node/296 for more information.

To workaround this limitation, the SQLITEX driver comes with it's own bundled SQLite library. However, it can also be configured to use the system sqlite library when it's possible.

The SQLITEX driver is used by WebIssues Client 1.0 in place of the RDB component used in previous version.

Documentation

You can find the full documentation for this component at doc.mimec.org/articles/sqlitex/. It is also included in the source package.

History

1.1 (2012-04-26)

  • updated SQLite to 3.7.11
  • updated the SQLite driver to Qt 4.8
  • removed the usage of QString::fromUtf16()

1.0 (2011-12-19)

  • initial version

Downloads

This code is licensed under the GNU Lesser General Public License, for compatibility with code from Qt which it incorporates, and to make it possible to use it in commercial applications.

See also:
  • list of all SQLITEX releases on the SourceForge.net download page
  • accessing the current development version directly from the WebIssues source repository
Filed under: Blog

Tooltips for truncated items in a QTreeView

It is quite common in various applications to display tooltips for truncated items in list views and tree views. Such functionality was present in Qt 3, but in Qt 4 the application, or rather the model, is fully responsible for providing the tooltip using the Qt::ToolTipRole and such automatic behavior no longer exist. You can obviously return the same text for both Qt::DisplayRole and Qt::ToolTipRole, but then tooltips are shown for all items, whether they are truncated or not. It doesn't look very well.

It's surprisingly hard to find a solution. The best I could find was this thread on the qt-interest mailing list. It suggests subclassing the view and overriding the tooltip event. I felt that there must be a better way, so I looked into the source code of QAbstractItemView. It turned out that since Qt 4.3, handling tooltips (and various other help events) is delegated to... the item delegate.

The definition of a custom item delegate may look like this:

class AutoToolTipDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    AutoToolTipDelegate( QObject* parent );
    ~AutoToolTipDelegate();

public slots:
    bool helpEvent( QHelpEvent* e, QAbstractItemView* view, const QStyleOptionViewItem& option,
        const QModelIndex& index );
};

Notice that the helpEvent method is a slot. It should be a virtual method; however adding a new virtual method to an existing class would break binary compatibility with earlier versions of the Qt library, so instead this method is invoked dynamically using the slots mechanism.

In order to check if the given item is truncated or not, we simply have to compare its visual rectangle (which can be retrieved from the view) with the size hint (provided by the item delegate itself). The full code of the helpEvent method looks like this:

bool AutoToolTipDelegate::helpEvent( QHelpEvent* e, QAbstractItemView* view,
    const QStyleOptionViewItem& option, const QModelIndex& index )
{
    if ( !e || !view )
        return false;

    if ( e->type() == QEvent::ToolTip ) {
        QRect rect = view->visualRect( index );
        QSize size = sizeHint( option, index );
        if ( rect.width() < size.width() ) {
            QVariant tooltip = index.data( Qt::DisplayRole );
            if ( tooltip.canConvert<QString>() ) {
                QToolTip::showText( e->globalPos(), QString( "<div>%1</div>" )
                    .arg( Qt::escape( tooltip.toString() ) ), view );
                return true;
            }
        }
        if ( !QStyledItemDelegate::helpEvent( e, view, option, index ) )
            QToolTip::hideText();
        return true;
    }

    return QStyledItemDelegate::helpEvent( e, view, option, index );
}

If the item is truncated, the display text is retrieved and displayed as a tooltip. Otherwise the default handler is called, so a custom tooltip may be displayed. If you want, you may reverse this behavior and only display the automatic tooltip if there is no custom one, or remove the call to the default handler if there are no custom tooltips.

Also notice that the text is wrapped into a <div> tag. That's in case the text is really long. When a HTML text is passed to the tooltip, it will be automatically wrapped into multiple lines if necessary. Otherwise the entire text would be displayed as a single line which may not fit on the screen. The Qt::escape method replaces any special characters with HTML entities to ensure that the text is displayed correctly.

All we have to do to enable automatic tooltips for a view is to assign our delegate to it:

    view->setItemDelegate( new AutoToolTipDelegate( view ) );

Note that it will also work for other kinds of views, not only QTreeView.

Filed under: Blog
Syndicate content