My blog has been moved to ariya.ofilabs.com.

Monday, June 04, 2007

I must have done it half a dozen times

Coming back from Berlin, I just realized that I got that stream of ideas again, of all things just now when my TODO list is unbelievably long, filled with all those backlog items for Real Life, KOffice, my PhD, and assorted fun projects. Granted, probably filling the TODO is still much better than having an empty one...

My time in Berlin was too short, I managed to have conversations with some, but unfortunately so little time to do everything.

(Picture taken in Berlin Hauptbahnhof)

Friday, June 01, 2007

Berlin (again)

Yeah, it was only two weeks ago but soon I'll be visiting Berlin again. This time is however only to have some fun in LinuxTag 2007, which, for the first time takes place in Berlin's Messe. KDE will be there and there are lots of interesting talks.

Thursday, May 24, 2007

SpeedCrunch's tip of the day

Typically, "tip of the day" feature is not really loved. Often, the dialog for showing the tip blocks the main view of the application. Worse, this dialog is even modal, you have to click it to make it disappear.

For SpeedCrunch upcoming version 0.8, I play around with the idea of showing a short tip as a yellowish widget inside the main window. It will disappear automatically after couple of seconds (even with some smooth translucent and animation effect). I'm still thinking whether the tip should be displayed at start up, or only from a menu item.

SpeedCrunch tip of the day

I hope this kind of tip is non-intrusive and yet allows the users to learn a thing or two about SpeedCrunch features.

So, what do you think?

(Yes, I know there is typo in the screenshot :-)

Monday, May 21, 2007

digest the curves, honor the pixels

Continuing my last year's GSOC, finally I managed to implement support for importing embedded raster images in libwpg. As with other graphics formats such as SVG, PDF, and ODG, WPG allows pixmaps or images to be combined with the vector graphics. It was a bit difficult because raster images are typically compressed using RLE (run-length encoding) and it was not too trivial to decode it. And I still do not code all possible depth/format yet. But finally, here is the mandatory click-to-enlarge screenshot:

WPG in Corel PresentationsWPG shown in Perfectspot

Left is the original WPG which I made in Corel Presentations by placing this beautiful windmill in Bremen together with a windmill picture from the clip art. Right is the WPG file opened and showed in Perfectspot (the all-around WPG viewer and converter).

Note that I'm waiting for Qt 4.3 before making a first stable release of Perfectspot (and also libwpg, provided that all image loading support is good enough). The reason is because it needs ObjectBoundingMode for QGradient which really simplifies the code. That's why, in the above screenshot, the gradient is not yet properly rendered in Perfectspot.

In related story, thanks to our very own Master Fridrich, libwpg-based WPG importer is going into ooo-build. So at least the next version of Novell's OpenOffice.org will be able handle those WPG files.

Sunday, May 20, 2007

Alternating row colors, in group

Alternating row colors is a very common user interface pattern, the most used example is the playlist in Apple iTunes. With different color every other row, the table or a long list looks more pleasant and easier to use.

However, if your list is rather vertical than horizontal, i.e. it is not that wide, but rather quite tall, and only consists of one or two columns, sometimes it helps to color not every row but a group of row. The example is shown here. The leftmost list widget has the same white color for all rows, the middle one uses alternating row colors (which looks rather "busy"), and the last one colors every 3 rows. Which one do you think is better?

Plain color Row Grouped

If your list is an instance of QListWidget, QListView or anything derived from QAbstractItemView, it is very easy to enable the alternating colors, just use alternatingRowColors property.

Alas, for grouped alternating colors for QListWidget, you must do some additional work, e.g. (works well for rather static items):

  int group = 3;
  list->setUpdatesEnabled( false );
  for(int i = 0; i < list->count(); i++)
  {
    QListWidgetItem* item = list->item(i);
    QBrush c = ((int)(i/group))&1 ? palette().base() : palette().alternateBase();
    item->setBackground( c );
  }
  list->setUpdatesEnabled( true );

Multiple column list is often made from QTreeWidget with only top level tree items. In this case, grouped alternating colors can be achieved using e.g. (for two columns, create a loop for more):

    int group = 3;
    tree->setUpdatesEnabled( false );
    for(int i = 0; i < tree->topLevelItemCount(); i++)
    {
      QTreeWidgetItem* item = tree->topLevelItem(i);
      QBrush c = ((int)(i/group))&1 ? palette().base() : palette().alternateBase();
      item->setBackground( 0, c );
      item->setBackground( 1, c );
    }
    tree->setUpdatesEnabled( true );

You can of course save some microseconds if you cycle the background color while iterating the items.

In addition, you may want to put some logic to prevent coloring if the number is item is e.g. less that 2*group. Otherwise, 4-item list will look odd, as only the last item has different background color.

Saturday, May 19, 2007

QEMU 0.9 with acceleration on SUSE 10.2

QEMU version 0.9 is already out for some time, but AFAIK no official package is available for openSUSE Linux 10.2 yet. Here are some steps I did to have QEMU 0.9 with accelerator (kqemu) on SUSE 10.2. The motivation is simple: I'd like to have a faster system for filter development.

QEMU 0.9 comes, among others, in binary package. I found out that this works well, so just download qemu-0.9.0-i386.tar.gz then unpack it to /. You'll see some new stuff in /usr/local/.

Next step is to install and use accelerator. This time I did compile it from source. First, get kqemu-1.3.0pre11.tar.gz, unpack it, then run the usual steps: ./configure follows by make and sudo make install. Don't forget to have kernel sources (install kernel-source package from YaST if necessary) in your system before doing this.

Now do the following:

export device="/dev/kqemu"
sudo rm -f $device
sudo mknod --mode=0666 $device c 250 0

After that, load the accelerator (kqemu) kernel module:

sudo /sbin/modprobe kqemu major=250

Now, run your virtual machine using the extra -kernel-kqemu option, e.g:

qemu -hda vdisk.qcow -kernel-kqemu

If you forget to load the kqemu kernel module, you'll get the following error message:

Could not open '/dev/kqemu' - QEMU acceleration layer not activated

otherwise, nothing shows up and your virtual machine is executed as usual.

To verify that kqemu works, activate the monitor using Ctrl+Alt+2, then type in info kqemu followed by Enter. You should see:

kqemu support: enabled for user and kernel code

(Exit from the monitor using Ctrl+Alt+1)

If, for some reason, you don't want to run the virtual machine with acceleration, use the option -no-kqemu, e.g.:

qemu -hda vdisk.qcow -no-kqemu

Now, info kqemu on the monitor would give:

kqemu support: disabled

I tested QEMU 0.9 with Windows NT 4.0 as the guest operating system. Even without acceleration, I've seen performance improvement compared to previous versions of QEMU. With acceleration (kqemu), it was even faster, although the kqemu documentation says only Windows 2000 and XP are supported. Benchmark done using CPUBench showed that the virtual machine runs roughly equal to a 300 Mhz and 1.3 GHz system without and with kqemu, respectively. Now, that's an improvement!

Happy virtualizing...

Sources:
http://fabrice.bellard.free.fr/qemu/kqemu-doc.html
http://fabrice.bellard.free.fr/qemu/kqemu-doc.html
http://kidsquid.com/cgi-bin/moin.cgi/QemuOnLinux

Thursday, May 17, 2007

Newton and the apple

Physics Teacher: "Isaac Newton was sitting under a tree when an apple fell on his head and he discovered gravity. Isn't that wonderful?"

Student: "Yes sir, if he had been sitting in class looking at books like us, he wouldn't have discovered anything."

from jokes4all.net

Monday, May 14, 2007

On these hands and knees I'm crawlin'

Time flies. KOffice sprint weekend in Berlin was just over. I couldn't believe I was on my bed again this morning. It was lots of fun, plenty of food, interesting talks, endless excitement, and most importantly, I got to see many great fellow KOffice hackers in real-life.

In terms of lines of code, I wasn't that productive. But I did managed to fix the annoying column/row resizing tip in KSpread and cleaned up some stuff so that krazy score is going to the sane level again. I checked our list of bugs and already had plan for few of them. The unit test for some spreadsheet functions would hopefully get some love as well. Also, thanks to our filter framework, I could work on a Karbon filter even before Karbon 2.0 is 100% ready. And I promised jaham that I'll help with the SVG to/from ODG stuff. There was also a buzz to finally start really using my latest work on KoXmlReader for all KOffice ODF loading code so that we won't have problem with memory consumption again when working with big documents.

For more details, summary and pictures, see KOffice ODF Sprint Kickoff on the Dot™. Update: and also KOffice ODF Sprint Report.

Thursday, May 10, 2007

berlin, berlin

So it'll be my n-th trip to Berlin. We're going to have KOffice ODF Weekend, supported by KDE e.V and KDAB. 17 16 heads, lots of hacking, and rainy weather look like a great combination.

Monday, May 07, 2007

point seven

Finally, SpeedCrunch version 0.7 has been released. Compared to the last beta, this final release has some fixes for potential crash (due to Q3TextEdit), which is also reported in Launchpad.

So, get it while it's hot. Packages are already available for Windows, Mac OS X (universal binary), Fedora, OpenSUSE, Gentoo, and Debian. Or just compile it from source if you feel brave. See the download page for details.

For some stuff which will make it into the upcoming 0.8, I'm still preparing an interesting screencast. Stay tuned.

Friday, April 20, 2007

Custom toggle action for QDockWidget

Thanks to QDockWidget::toggleViewAction, if you want to create an action (and placed in in the menu, for example) to switch a dock widget on and off, it is very simple indeed. The text of the action will be the title of the dock. If you have more than dock widgets, this can be combined together in a sub menu "Show Docks", just as illustrated below:

When that menu item (and the corresponding action) is checked/unchecked by the user, magically the dock will show/disappear.

But what if you want to create your own toggle action? For example, you want to customize the text of the action to be a bit more descriptive, say "Show Function List". Or perhaps you just want the total control.

Well, you can create your own actions and get this result:

which can be realized by the following code:

  m_actions->showHistory = new QAction( tr("Show Expression &History"), this );
  m_actions->showFunctions = new QAction( tr("Show &Functions List"), this );
  m_actions->showHistory->setToggleAction( true );
  m_actions->showFunctions->setToggleAction( true );
  connect( m_actions->showHistory, SIGNAL( toggled(bool) ), 
    m_historyDock, SLOT( setVisible(bool) ) );
  connect( m_actions->showFunctions, SIGNAL( toggled(bool) ), 
    m_functionsDock, SLOT( setVisible(bool) ) );

So far so good. Everytime you toggle the menu item, the docks can disappear and reappear.

However, it's not completely foolproof. You can, infact, make the dock disappear by closing it manually, i.e. clicking on the X button on the dock title bar. But by doing that, the "checked" status of the action itself is not properly adjusted (i.e. it is still "checked" while the dock is long gone).

With Qt 4.3, the solution is easy: use visibilityChanged signal of QDockWidget:

  connect( m_historyDock, SIGNAL( visibilityChanged(bool) ), 
    m_actions->showHistory, SLOT( setChecked(bool) ) );
  connect( m_functionsDock, SIGNAL( visibilityChanged(bool) ), 
    m_actions->showFunctions, SLOT( setChecked(bool) ) );

If, for whatever reason, you're stucked with Qt 4.2, then you have to find another remedy since visibilityChanged does not exist there. There are many ways to do this.

A particularly complicated but looks-elegant solution is by hijacking trapping the show and hide event of the docks using eventFilter trick. So, hook the event filters during docks construction:

  m_historyDock->installEventFilter( this );
  m_functionsDock->installEventFilter( this );

and do something like this in the window's event filter:

bool MyWindow::eventFilter( QObject* object, QEvent* event )
{
  if( object == m_historyDock )
    if( event->type() == QEvent::Hide || event->type() == QEvent::Show )
      m_actions->showHistory->setChecked( event->type() == QEvent::Show );

  if( object == m_functionsDock )
    if( event->type() == QEvent::Hide || event->type() == QEvent::Show )
      m_actions->showFunctions->setChecked( event->type() == QEvent::Show );

  return false;
}

Looks good? Not really. Because for all this trouble, you can just do the same in these two lines of code (the simple and yet effective solution):

  connect( m_historyDock->toggleViewAction(), SIGNAL( toggled( bool ) ),
    m_actions->showHistory, SLOT( setChecked( bool ) ) );
  connect( m_functionsDock->toggleViewAction(), SIGNAL( toggled( bool ) ),
    m_actions->showFunctions, SLOT( setChecked( bool ) ) );

Any other solution, perhaps?

Thursday, April 19, 2007

on winning in life

Life is a game, and if you aren't in it to win, what the heck are you still doing here?

-- Linus Torvalds