Sunday, July 05, 2009

Managing multiple Qt versions with Git clone

Like many Qt developers I have many different versions of Qt on one computer. In the past I used to have a copy of nearly every tarball and a built version. My /home/ben/dev directory looked something like this:
...
qt-all-opensource-src-4.5.0/
qt-all-opensource-src-4.5.0.tar.bz2
qt-all-opensource-src-4.5.1/
qt-all-opensource-src-4.5.1.tar.bz2
qt-all-opensource-src-4.5.2/
qt-all-opensource-src-4.5.2.tar.bz2
...

Now that the Qt repository has been open for a while we can take advantage of a nice feature of git clone called local cloning. On my computer I have a primary Qt repository (/home/ben/dev/qt-master/) which has has remotes pointing to my personal Qt fork and the main Qt repository.

Rather then downloading a tarball of 4.5.2 I now do a local clone of Qt and then checkout the tag "v4.5.2". Although Gitorious does not list tags (missing feature?) both Qt 4.5.1 and 4.5.2 have been tagged in the Qt Git repository.
git clone -l qt-master qt-4.5.2
cd qt-4.5.2
git tag -l # List the available tags I can checkout
git checkout v4.5.2
A local clone will share object files when possible saving you a lot of hard drive space. For Qt versions older then 4.5.1 I still have the tarballs, but going forward there are a lot of advantages to using this beyond saving space. In the past when tracking down a bug in a specific release I have often tweaked the code or applied a patch. Now that the releases are fully backed by Git I can quickly revert back to the release as well as using tools like git blame and git log to get much more information about any files I am investigating. You also get the tests and util directories which are stripped out of releases.

In addition to the releases I also have a clone for the Qt 4.5 branch, what will be 4.5.3. qt-master is the original Git repository which tracks what will become Qt 4.6. After this change I ended up with a directory like this:
...
qt-all-opensource-src-4.5.0/
qt-all-opensource-src-4.5.0.tar.bz2
qt-4.5.1/
qt-4.5.2/
qt-4.5/
qt-master/
...

Like many Qt developers I have written a bash script 'qs' that I have in my shell profile to quickly list and switch between Qt directories.
'qs' - Display current Qt version
'qs ' - List all qt directories
'qs qt-4.5.2' - Swap environment to use Qt 4.5.2
'qcd' - Change to the current Qt's directory

This Git clone trick of course applies to any Git based project, not just Qt, but it is yet another hidden gem of the decision to open the Qt repository.

Wednesday, May 13, 2009

Open Qt repository and hidden gems

On Monday Qt Software launched the public repository for Qt. Already there are more then a dozen patches waiting for review in the merge request list and no doubt there will be many more. To help developers submit patches that are higher quality and more likely to be accepted a number of documents have been published on the Qt wiki. Beyond the wiki in the source repository there are new things that could not previously be found in the snapshots or releases. With so many new things I wanted to highlight a few of the items I found most interesting.

Qt Coding Style Followed not only by Qt, but by other projects such as Arora and applications in KDE. Having a common coding style makes code easier to read and review. In the past few years I have seen many applications adopt this style and I look forward to seeing the usage grow.

Api Design Principles An updated version of the old Qt Quarterly article Designing Qt-Style C++ APIs from the first paragraph: "This document tries to summarize the know-how we've accumulated on designing Qt-style APIs. Many of the guidelines are universal; others are more conventional, and we follow them primarily for consistency with existing APIs."

The Little Manual of API Design by Jasmin Blanchette’s In the wiki page for Api Design Principles you find a link to the this pdf which is now public. This first rate book should be manditory reading by any programmer. While many of the examples are from Qt and in C++ most of its ideas apply beyond Qt and C++. Rather then doing it a disservice and trying to describe it, here is the table of contents which gives a good overview.

1 Introduction 5 
2 Characteristics of Good APIs 7
2.1 Easy to learn and memorize . . . . . . . . . . . . . . . . 8
2.2 Leads to readable code . . . . . . . . . . . . . . . . . . 9
2.3 Hard to misuse . . . . . . . . . . . . . . . . . . . . . . 10
2.4 Easy to extend . . . . . . . . . . . . . . . . . . . . . . 12
2.5 Complete . . . . . . . . . . . . . . . . . . . . . . . . . 13
3 The Design Process 15
3.1 Know the requirements . . . . . . . . . . . . . . . . . . 15
3.2 Write use cases before you write any other code . . . . . 15
3.3 Look for similar APIs in the same library . . . . . . . . 16
3.4 Define the API before you implement it . . . . . . . . . . 17
3.5 Have your peers review your API . . . . . . . . . . . . . 17
3.6 Write several examples against the API. . . . . . . . . . 18
3.7 Prepare for extensions. . . . . . . . . . . . . . . . . . 18
3.8 Don’t publish internal APIs without review. . . . . . . . 18
3.9 When in doubt, leave it out . . . . . . . . . . . . . . . 19
4 Design Guidelines 21
4.1 Choose self-explanatory names and signatures . . . . . . . 21
4.2 Choose unambiguous names for related things . . . . . . . 22
4.3 Beware of false consistency . . . . . . . . . . . . . . . 23
4.4 Avoid abbreviations . . . . . . . . . . . . . . . . . . . 25
4.5 Prefer specific names to general names . . . . . . . . . . 25
4.6 Don’t be a slave of an underlying API’s naming practices . 26
4.7 Choose good defaults . . . . . . . . . . . . . . . . . . . 27
4.8 Avoid making your APIs overly clever . . . . . . . . . . . 28
4.9 Pay attention to edge cases . . . . . . . . . . . . . . . 28
4.10 Be careful when defining virtual APIs . . . . . . . . . . 30
4.11 Strive for property-based APIs . . . . . . . . . . . . . 31
4.12 The best API is no API . . . . . . . . . . . . . . . . . 32

Codeing Conventions and Binary Compatibility Workarounds Two good documents that walk through a number of issues that Qt has to deal with being a library that is used on many platforms and compilers. An interesting read for anyone who uses C++ or Qt.

Autotests and Benchmarks After several years of discussing it, the Qt autotests have finally been published. Everyone in KDE can finally checkout how class Foo is tested and when writing patches for Qt an attempt should always be made to write a matching autotest. See some interesting usage of qtestlib and get plenty of example of how to test gui widgets. For those who are writing their own tests check out my QAutoTestGenerator tool which generates test stub files for you to help get you started. Hopefully having this large set of tests open will encourage more Qt projects to have tests. For those who are using Git and qtestlib I have written a git hook that can be found in the Arora repository that will run the matching autotest for files you change to check for any regressions before commiting.

The full commit log for Qt While in the past the qt-snapshot git repository gave a one day granularity the new repository includes every commit with the commit log. The other day while tracking down the QTemporary bug in 4.5.1 I wrote a little test application and Thiago used git bisect to find in twenty minutes the exact commit that had caused the breakage.
git bisect start HEAD v4.5.0 -- src/corelib/io
git bisect run sh -c 'LD_LIBRARY_PATH= make sub-corelib && (ulimit -n 250; /tmp/qfile-bug/qfile-bug)'
With the full commit log tools like bisect and blame become even more useful for inspecting the Qt source code.

With the Qt sourcecode on gitorious It will be easier for developers that need a bug fixed to help contribute and get it fixed in Qt faster. Those who use Qt and want to understand how something works or why it was developed in a particular way will be able to more easily explore the code base. And maybe KDE can even remove the legacy qt-copy. No doubt many good things will come out of the open Qt repository and I look forward to seeing what the community contributes.

Monday, April 20, 2009

World Smallest Transformers


In 2003 Takara released a Transformers toy line that has been dubbed by the fans World Smallest Transformers or WST for short. They are fully transformable two inch tall versions of a bunch of the classic 80's toys. Due to the size and small parts they were only ever sold in Japan. Not too many were made and they were very hard to come by and to make matters worse they were sold in unmarked boxes so you never knew which toy you received. Also there was a different ratio for each toy in the master box making it difficult to collect them all while in the process getting a ton of the common ones. Googling around I was unable to find the ratio's for each toy, so I have put together a list of the toys with the ratios so the data will always be on the Internet.

Wave 1: (2003)
GTF 01A Convoy A (aka Optimus Prime truck cab) 8/48
GTF 01B Convoy B (aka Optimus Prime trailer) 2/48
GTF 02 Lambor (aka Sideswipe) 12/48
GTF 03 Starscream 6/48
GTF 04 Bumble (aka Bumblebee) 12/48
GTF 05 Soundwave (with Jaguar aka Ravage) 6/48
GTF X-1 Skywarp 1/48
GTF X-2 Bumble Red Version (aka Cliffjumper) 1/48

Wave 2: (2004)
GTF 06 Convoy Anime Version (aka Optimus Prime truck cab with blue windows) 12/48
GTF 07 Megatron 8/48
GTF 08 Meister (aka Jazz) 2/48
GTF 09 Prowl 6/48
GTF 10 Alert (aka Red Alert) 6/48
GTF 11 Thrust 12/48
GTF X-3 Streak (aka Silverstreak) 1/48
GTF X-4 Convoy White Version (aka Ultra Magnus cab) 1/48

Dengeki Hobby exclusive Smallest VSX Giftset:
VSX Convoy (variation of Anime colors)
VSX Megatron (aka Megaplex)

Wave 2.5: (2004)
CSV Starscream (from Series 1) 12/48
CSV Soundwave (from Series 1) 8/48
CSV Megatron (from Series 2) 12/48
CSV Convoy Anime Version (from Series 2) 6/48
CSV Meister (from Series 2) 6/48
CSV Hot Rodimus (aka Hot Rod) 2/48
CSV Convoy Container (aka Optimus Prime Anime Trailer) 1/48
CSV Thundercracker 1/48

Wednesday, March 18, 2009

PlanetQt.org launch

After more then a year of thinking about doing it I finally setup planetqt.org and after getting the initial kinks out am officially launching it. While KDE is a major user of Qt there are many applications and developers out there who are not part of the KDE project or who's blogs/news really don't really fit on planetkde.org (or the freedesktop planet). Because of this there are a lot of really interesting Qt projects/tools/stuff out there that people don't know about. So that is why I started Planet Qt. Being made up of people I thought the frame from the Qt4 dance seemed to be a nice logo.

Submit atom/rss feeds for blogs about Qt development or the news feeds of applications/libraries that use Qt and I will add them.

Enjoy!

Monday, March 02, 2009

Tiling An Image With FractalFill

Last summer Adam and I looked into how to speed up tiling an image. In particular we were using QImage (Not a QPixmap so X11 isn't involved in this) and tiling an image on it. This is a pretty common operation, especially on the web where many web pages have repeating backgrounds on items. We came up with a few different ways to do this in Qt.*
  • Naive
    loop over the height 
    loop over the width
    fillRect(tile)

  • QPainter::eraseRect
    Set a background brush to be the tiling image.
    call painter.eraseRect(QRect(0, 0, image.width(), image.height());

  • QPainter::fillRect
    call painter.fillRect(QRect(0, 0, image.width(), image.height(), brush(tile));

  • FractalFill
    painter.drawImage(0, 0, tile)
    while we haven't reached the width and height
    copy everything we have done so far to the next location

Benchmarking this we discovered that eraseRect was pretty horrible, but much more surprising was that our FractalFill algorithm that we tossed together was faster then all of Qt's method. (If any graphics ninja's want to suggest a even better algorithm we are all ears) Adam blogged about this some of the Trolls responded saying that Qt's painting had improved in a private branch which would be part of Qt 4.5. Now that Qt 4.5 is almost out I thought I would revisit to see how the painting performance numbers shaped up to be.

Along with the four algorithms there are two more that are added to the benchmark (Colored yellow in the graphs).

  1. A base line, something that we shouldn't be able to be faster then: just calling painter.fillRect(QRect(0, 0, width, height), color);

  2. Using the FractalFill to paint the whole image with a color.

First up is RGB16 with: 1000x5000





Qt 4.5 really has improved upon Qt 4.4. The problems in eraseRect are gone and everything is faster across the board moving to 4.5 and even better when using the raster engine. But more surprising is that FractalFill is still faster then the two QPainter functions.

Same format (RGB16), but in a larger size: 5000x5000





Again it is clear that eraseRect has been fixed and overall painting has been improved slightly.

Moving on to ARGB32: 1000x5000




And in 5000x5000





On this last one with the larger image sizes I started getting larger differences in the tests results. On ARGB32 the performance seemed to be about the same or slightly better.

Overall performance is much better in Qt 4.5 then 4.4. A big congrats to the Trolls for all their hard work. Painting speed has improved across the board decreasing the runtime of all of the functions. FractalFill is still faster then using QPainter's fillRect or eraseRect so for the time being if you looking for something faster then Qt's fill functions for tiling this might be useful for you.

Notes:
I have uploaded the source for the test application to a GitHub repository. I ran the application multiple times on my computer to generate the numbers using the release version of Qt, building from qt-snapshot with 4.3.2 on ubuntu and qt3compat turned off. Now that Qt 4.5 is out it would probably be worth converting to the new benchmark tool. I used Google's graph service to generate the graphs.

* Analyzing each algorithm to determining their Big-O notation is left as an exercise to the reader. ;)

Friday, February 20, 2009

Arora 0.5 and Oxygen Style



Tonight I tagged Arora 0.5. And with every release starts development on the next release. One of the things I would like to improve for 0.6 is integration with KDE4. To help do that I have started a wiki page of KDE4 items. When using Arora on KDE a bunch of the first issues everyone runs into are really just improvements that need to be made to the Oxygen style. Little things like returning the KDE icons for back/forward, returning the correct size check boxes in QtWebkit, and supporting the new QTabBar style hints in Qt 4.5 will really help Arora fit in better with KDE 4. Of course these fixes will benefit everyone who uses QtWebKit in their application and anyone KDE application that uses the new QTabBar features. So I am putting out a request for help. If you happen to have your box all setup for KDE development and have a few minutes to spare helping making Oxygen an even better style would be most appreciated.

Friday, February 06, 2009

Comments rating systems, a close look at giving points

On many social news sites users can give and take points on comments. The purpose of the points is to give hints about what comments are worth reading. But upon closer inspection this method often fails to provide a way to let the sites software sort or highlight good comments.

A lot of time and effort is spent perfecting the algorithm used to generate the order of stories, but when it comes to user comments on each article the trend the past few years has been to allow any user to vote up or vote down a comment and to sort on the values. This up down method seems to provide very little real value and produces very poor results as a means of sorting.

When a user sees a comment the basic version of the algorithm that users go through is something like this:

"If I see a post that looks good I vote it up. If I think it is wrong I vote down."

The number of points a good post gets is directly related to the number of users that read the post. The more users read the post the more are likely to award it points. A good post A posted at time 0 could get 100 points and the same post made at time +1hour will get 50 points and the next day will only get 3 points. At the same time a bad post B posted at time 0 can still get 8 points.

Or to sum it up with one question:
Is a comment with 47 points better then one that has 46 points? Frequently you will find the answer to be yes, no, and maybe depending upon when the post was made and having very little to do with the actual content. Because comments are not created at the same time the points that they each get can't accurately be compared without taking into account extra information. You could take into account the time sense the article was posted, the number of people who saw the comment, the number of people who voted on comments and the total votes given at the time when the vote was cast. All this does it make it more complicated so the same system can be used rater then asking of the system should have been used in the first place.

For many of the social new sites the comments were second fiddle to the main page. Once the jewel of the site the article sorting was working then comments were added. Many social news sites the past few years have employed some sort of up/down voting system for articles. Developers being developers decided to reuse this same code on comments. Lets users up/down vote on any comment and sort based upon value and blam job done in no time flat. Of course the article sorting isn't actually based upon only the value of votes, but takes into account time as a factor of the ranking.

It seems as though sorting comments was created out of the laziness of developers. They do have one thing going for them though. When a site is small there will not be too many comments on articles so users can quickly read all of the comments. For a small number of comments the sorting doesn't matter that much. It is only when you get a large enough base to get many good comments that the issue comes to light. Of course by that time if you have lots of users there is no real incentive to make the site better because the incentive of making something better to get users is diminished.

While social news sites think that their secret sauce is the front page I wouldn't be surprised if the comments page was of much more value. After playing around with the issue for way to long I ended up with a model very similar to the one slashdot already has. For any given comment it can be ranked from -5 to +5 and given a type. You end up with comments that have ranks like: +5 funny. +4 informative, -3 troll, etc. It takes very few users to agree that something is informative or funny and should get a value of -3 or +5.

The number of points a good post gets is directly related to the value the users find the post to be. This will results in the comment changing values less and less as time goes by (reaching its true value). A good post A posted at time 0 will have 0 points, but two minutes later will be at 3 and from then on some might say it is 2 some might say it is 4, but it quickly approaches what everyone feels the comment actual worth is. Compared this to posting the comment A after one hour and it will probably again be marked at 3 by a few users. This allows for much better comparisons between comments.

Combined with the small point scale is adjectives. This makes the user not just say "I like this", but have to think about what they like which results in much better scores. It also gets the added benefit of allowing users to do things like automatically give -1 points for funny comments if they find them annoying (or +2 in the opposite case).

To add to the debate there are several live examples of the different systems (often times they even cover the same article!). First going back to the objective which is to rank or highlight good comments for readers so they don't have to read everything. This includes getting rid of junk/spam/trolls. Now head over to slashdot and click on an article from yesterday. View comments by default it shows +4 and higher. They are pretty good and informative. Now go to reddit. While it is able to get rid of spam comments it displays everything having no such thing as +4 or higher and even if you sort by Top you still find that that non-informative, but early comment (which may or may not be really good) is right at the top with a huge number of points and you have to scroll around reading everything, attempting to find a post of any real worth. The good comments are just as likely to be near the bottom with 4 points as near the top with 400. When a social news site is unable to bring good comments to the viewer a good chunk of the value of the social new site is lost.

Having points for comments is a system that is so easy to implement that it will probably never go away, but a closer inspection shows that it really doesn't do a good job of the basic feature it was created for which is to allow the system to give hints about what comments are worth reading.

While I doubt many sites will change what they are doing this will hopefully spawn some conversations for developers who are creating the next generation social new site. While the slashdot system might not be the best we need to take a step back and look to see what the objective of ranking comments and how to best achieve that.


Photo by dougww

For another fun comparison blog like this one see the blog post that discusses two different ways to find the most attractive girls.

And for a blog discussing problems with giving users infinite karma points checkout Joshua Gross's Qualifying “Web Karma”: It shouldn’t be a game.

Update: Reddit has switched to a new comment system that attempts to resolve several of the problems listed. Read more on their blog: reddit new comment sorting system