API-Design or How I Learned to Love Writing Docs

After a short trip back back home to see the “Kölner Lichter”, one of the most impressive fireworks in germany with my gf, I went back to Berlin on Sunday. With plenty of time on my hand during the train trip, I decided to revisit a project I started in 2005: CollapsibleWidget. After I have probably missed every deadline for inclusion of this little thing into kdelibs for KDE 4.0, I still want to bring it into shape for use in individual parts of KDE, especially the control center.

The widget is lurking around in playground for a good while now, and Aaron, our plasma god, has even added nice collapse animations to it. So it works, looks fancy, why the worry?

Being a good libs coder, I was unsatisfied with the class I originally wrote for an number of reasons:

1. The API involved the concept of a container class that holds a number of CollapsibleWidgets. This class is orthogonal to other widgets that might want to hold such an item and is therefore redundant.
2. The API of the widget followed no particular class known from Qt or KDE.
3. The naming conventions, code indentation levels, etc were non-consistant
4. The API documentation was basically non-existant.
5. As the Widget is composed of several items internally, it still uses an widget()/setWidget() idiom to handle setting the to-be-collapsed widgets.
6. No sensible focus/buddy handling

The first problem I was able to solve was number two: After discussing the issue a bit with some fellow trolls in the berlin office, we decided that it would probably be best to model the class closely around the API of QGroupBox. However I noticed that it does not make much sense to inherit from QGroupBox, as the API has several things that I have no use for (setFlat(), setCheckable(), etc.). I also don’t see a lot of potential for code reuse there. So I went and implemented most of the properties of QGroupBox, which looks pretty good, even if I am not yet sure if it makes sense to allow setting the labels alignment for instance.

Also I was looking for a way to get rid of number one, the container. Qt has a container class that allows for scrolling: QScrollArea. The container class actually inherits from QScrollArea, but sets it up in a convinient way, e.g. adds multiple, resizable widgets to a QScrollArea, which takes some extra API calls. I just got rid of the class, documenting the QScrollArea setup procedure in the docs. I was contemplating to add a static factory method to CollapsibleWidget, but since we live in times of GUI designers, I think I should rather try to work out a convinient way to use those classes in designer. So I went to talk to Friedemann, our local designer guru here at Trolltech. and this morning he implemented support for QScrollArea! This means you can now put arbitrary widgets and layout inside a ScrollArea in designer. Yay!

The need for designer integration also might also help me to get rid of number five and might ease to implement number six: Using the QPainter and QStyle API directly rather than using a QLabel and a QAbstractButton might help in reducing flicker, speeding things up and might also allow plain simple layouts, therefore avoiding the setWidget()/widget() hack.

As for number three: Code reindention was done quickly, and the API inconsistancy was pretty much automatically solved by approaching number four: While writing the API docs, one is quick to notice a lot of inconsistancies within the API. I corrected all I noticed along the way. I also realized that the Widget wasn’t actually a collapsible widget, but much more an expandable widget, since it’s collapsed by default. Also, talking about expansion is a lot more consistant with other parts of Qt (think Item views). Also, the widget is better described as an expandable group box, than just an expandible widget. After all, it’s even modelled after QGroupBox. After prepending a K (the class is supposed to become part of kdelibs some day, right? :), I ended up with the nameKExpandableGroupBox.

The code is in playground and comes with a small example to play around with. I’d appreciate your comments, especially on the name.

Writing documentation really helped me to improve the API a lot. So I put my thumbs up and put on a cheesy smile to tell you: “While writing API documentation, I expirienced enlightenment – and so can you!”

(ade, you SO owe me a beer for this one)

LinuxTag 2007 wrap up

So I am finally back home. Time to summarize the last few days sebas style:

  • Berlin is definately a nice place for LinuxTag, but we need sleeping opportunities that don’t require us to travel through the entire city to get to the fairgrounds.
  • Friedrichshain has really nice flat shares to stay.
  • My future collegues from the TT Berlin Offices are really cool guys (ok, who would have expected anything else? ;-))
  • Sven from Amarok, Dimitri from Trolltech and Sebas gave nice interviews during a live show on Deutschlandfunk.
  • Long train travels + Boredom + Power plug = Amazing productivity
  • And finally: Adriaan, I still have your towell.

Life is great and so is Berlin

So people asked under which stone I have been hiding lately. Of course exams cannot be the excuse for everything, so I present you another one:reallife. It has really hit me badly on this rather nice spring.

In other news, Trolltech sent along my nicest birthday present last night: My contract. So it’s finally official: I’ll be doing an internship at Trolltechs Berlin Office in Adlershof for 10 weeks starting July, 1st.

Now I am looking for a room in Friedrichshain. If you have any hints, sent them along privately or add a comment.

Ellipsis made easy

Many people have asked for an widgets like labels or buttons that can elide their text as the size of the widget underruns the text length in a visually appealing way. Text ellipses already happens: most widgets (or, since Qt abstracts that, many styles) use ‘…’. However, that doesn’t really look good and it was suggested that ellipsis could be better signified by fading out the last two letters. Dolphin has a hack to achive this with Qt 3, and it is incredibly complicated. So I sat down and looked what it takes to do it better with Qt 4. This is what the result looks like:

Note how the entire sentence is still readable now (at least for the majority of people), and it was really easy to do: I implemented a QLabel subclass that takes 6 lines of code in the paint event to do the actual fading using QGradient:


void ElideLabel::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter p(this);
QFontMetrics fm(font());
if (fm.width(text()) > contentsRect().width()) {
QLinearGradient gradient(contentsRect().topLeft(), contentsRect().topRight());
gradient.setColorAt(0.8, palette().color(QPalette::WindowText));
gradient.setColorAt(1.0, palette().color(QPalette::Window));
QPen pen;
pen.setBrush(QBrush(gradient));
p.setPen(pen);
}
p.drawText(rect(), Qt::TextSingleLine, text());
}

Yeah, really, that’s it. Nothing more to see here. Yes I know, The code doesn’t pass on all text flags that the QLabel API accepts, but hey, it’s a demo. One that made Peter want to replace the old algorithm in Dolphin with a QGradient-based one. The real trick here was to realize that constructing a pen with a brush inherits the gradient. Thanks to Zack for the hint!

CLT2007, LiMux, Where Documentation Really Belongs

Last Weekend, KDE had a booth at Chemnitzer Linux-Tage 2007, one of the best Open Source / Free Software Community events that I am aware of. I went over to Chemnitz with my LUG friends and was warmly welcomed by my friends and hosts Antje, Daniel and KF.

The booth was staffed with a lot of well known developers like Alex Neundorf of CMake fame as well as fresh blood like Bernhard Schiffner, who did not only volunteer to help out on the booth but also brought some additional hardware and a precompiled KDE 4 which we happily showed off. If you are a KDE lover and want to support KDE, follow Bernhards example and subscribe to KDE-Promo to help your local promo team.

The most discussed topic was the Dolphin vs. Konqueror that also caused quite some heat on the Dot. Another FAQ revolved around our choice against Beryl or Compiz as the default Window Manager in KDE 4. The reason is fairly simple: Both only work on modern hardware and with modern drivers. They are also not as well integrated in KDE 4 as KWin is, and it would be hard to get them there in some particular areas (think KIOSK). On the other hand, KDE 4 will support Beryl or Compiz just as well, so if you feel like using them, there is nothing in your way. Also let me point out that KWin maintainer Lubos Lunak (sorry for the spelling Lubos, not Unicode keyboard available) is working on some eyecandy in KWin, which he already blogged about.

But lets return to my little report: On Sunday, I gave fairly well attended two hour workshop on Qt 4 programming, which was very well received. I also had a couple of interesting meetings with several people. I might blog about some of them later. Most interesting for the purpose of this blog entry was the discussions I had with the people from LiMux (Linux in Munich). They were very interested when they learned about TechBase.

This is pretty much what I hoped for: The technical staff within the LiMux project is pretty much the combination of System Integrators and administrators that had a hard time to figure out KDE detail and they still have. However, there is hope now: Everything can be easily documented. Also there was one particular plea that I’d like to forward to all KDE developers: Don’t hide documentation in Subversion. No real word user will ever be looking there. Noone, really. Storing documentation in Subversion, even if it is not strictly general purpose documentation, is the best way to get people annoyed with your software, since they usually use packaged software. Use TechBase and don’t be shy to create new documentation. If you don’t feel confident about where to store new documents: Don’t despair! A lot of people are monitoring changes on TechBase and will put the articles where they belong.

Busy Days At 23C3, OLPC, WebKit

After visiting the family over christmas, I headed to Berlin on Wednesday to attend 23C3. Together with Holger Freyther I am representing KDE at this event and our friends from Wikimedia have given us a place to hack at their corner of the Conference building. Yesterday I used the opportunity to get contact to some of the mediawiki hackers to pass on some itching bug reports. Some of the problems are already resolved, others will be approached on tomorrows (or todays, depending on your timezone) Developer Wiki Friday.

On another note, I had the chance to get my hands on one of the OLPCs, as the laptop.org developers also seeked the productive and friendly atmosphere of the Wikipedia Corner. I can only agree with Sebastian: This is a device to actually care about and take care of: it’s both cute and powerful. The software (Sugar) still has some rough edges though and gecko-based browser app is really slow and unoptimized for the screen, which is a real pity.

That was motivation enough for us to go a small experiment: Can we run WebKit/Qt4 on the Sugar and have it use less memory footprint than gecko? Since Zack is on holidays, I fixed the Qt port based on a patch from Fredrik and filed the patch in the WebKit Bugzilla. Meanwhile Holger is busy to make Qt widgets work in GTK/Sugar. Let’s see if this will work out :).

Password-Input-Patch FAQ

Instead of individual replys to mails and other blogs, just a quick summary of answers to questions I received:

Q: You claimed QStyle::SH_LineEdit_PasswordCharacter didn’t exist Qt 3, but it does!
A: Yes, I didn’t really consider that to be honest. Mea cupla. Read this blog entry for an explaination.

Q: Can I add this to my style?
A: Sure you can, if you want users with older KDE versions to profit from it. Of course the nicer version would be to put it into KStyle and let everyone have it. But it’s simple and cheap enough to add, maybe with a KDE-Version #ifdef once KDE 3.5.6 is released with that patch.

It seems like the authors of Serenity and Polyester are already hooked. 🙂

Q: Will this be in KDE 3.5.x?
A: Maybe. I will use a patched KDE for a while. If no problems occur, I will ask for inclusion for KDE 3.5.6. Of course Maxim, the current KStyle maintainer, has the last word about it. In general it’s a fairly simple patch that adds less than 20 lines of fairly simple code. Also, the Kubuntu guys already added the patch to the kdelibs package of Feisty.

Update: I just committed the patch to SVN, so it will be part of KDE 3.5.6.

KStyle Pimped

When I wrote my entry on password characters. I thought it was a Qt 4 only thing. I didn’t even bother checking with Qt 3.3. Fortunately, Marco Martin, the author of Polyester asked me if he could use the code in his style. I checked QStyle in Qt 3 and indeed, QStyle::SH_LineEdit_PasswordCharacter is part of the QStyle API since Qt 3.2. My guess is that the Trolls introduced it in order to implement the XP- and/or OS X-styles.

That motivated me to patch KStyle, the base class for all KDE-styles, and look how pretty it is:


(click to enlarge)

PS: thanks go out to the folks who wrote Xephyr, a Xnest replacement capable of Xrender & friends. You guys made nested sessions on X a lot more bearable.

PPS: For all that keep asking: Yes, that means that with this patch, all KDE styles instantly show the new behaviour. Isn’t KDE great? 🙂

Password shadowing: Pimp My Plastique

I was wondering why KDE still uses asterisks for substition in password fields. Look at this example:

Well, in Qt 4 it’s really easy to change it. This is the QPlastique style using Unicode character 0x25CF, a bullet point. If that one doesn’t exiss in the current font it falls back to 0x2022, a slightly smaller bullet point. Only if the current font doesn’t provide either (which is fairly rare according to my tests), it will fall back to an asterisk. This algorithme is actually stol^Wborrowed from the Windows XP style, so why does Plastique still use asterisks by default? The reason is probably that it was supposed to resemble the Plastik style from KDE 3, which had to use asterisks since the

QStyle::SH_LineEdit_PasswordCharacter

style hint was not part of the QStyle API. in Qt 4 this style hint allows for specifying any other unicode character:

You might wonder why I think that this change, started by Apple in OS X and Microsoft in Windows XP is a good idea: Well first the character looks odd enough so that people will understand that this character is really supposed to shadow the password input. I know from personal experience that using asterisks, which can actually be part of a password tend to confuse some people. And secondly… well, it looks a lot better. It’s more centered in most fonts while asterisks are usually displayed upwards in the line edit.

(For the technically inclined, i have uploaded the sources for this small example, including a QPlastiqueStyle subclass that implements the change.)