OSGalaxy

published by vivek on 2007-07-05 16:40:16 in the "Open source coding" category
Vivek Gite A device driver is computer program allowing other computer programs to interact with a computer hardware device. Writing a Linux device driver is considered as a black art by many. If you ever been tempted to try writing a device driver, this howto will serve as a kick start guide: For many seasoned Linux developers, device [...]

> Read More... | Digg This!

published by Ariya Hidayat on 2007-05-24 14:34:10 in the "coding" category
Ariya Hidayat

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 :-)



> Read More... | Digg This!

published by Ariya Hidayat on 2007-05-20 08:03:28 in the "coding" category
Ariya Hidayat

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.



> Read More... | Digg This!

published by Ariya Hidayat on 2007-05-14 03:13:25 in the "coding" category
Ariya Hidayat

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 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 as 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 Kick on the Dot™.



> Read More... | Digg This!

published by Ariya Hidayat on 2007-05-10 10:49:08 in the "coding" category
Ariya Hidayat

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 heads, lots of hacking, and rainy weather look like a great combination.



> Read More... | Digg This!

published by Ariya Hidayat on 2007-05-07 15:50:25 in the "coding" category
Ariya Hidayat

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.



> Read More... | Digg This!

published by Ariya Hidayat on 2007-04-20 02:58:23 in the "coding" category
Ariya Hidayat

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?



> Read More... | Digg This!

published by Ariya Hidayat on 2007-04-18 02:06:48 in the "coding" category
Ariya Hidayat

Warning: don't try this in real world's application!

One advantage of dock widgets (using QDockWidget) is that the docks can be "stacked", either programatically using tabifyDockWidget or when the user explicitly places one dock on top of another. Example is shown below (for future version of SpeedCrunch, more about this in another blog post). There are two dock widgets: History and Functions, and at the moment they are stacked.

However, apparently the tab bar (QTabBar) which is used to choose the dock is always placed at the bottom. Or, using the Qt's terminology, it has the shape of QTabBar::RoundedSouth. Since there are other possibilities for tab bar's shape, e.g. RoundedNorth, would it be possible to make something like this, where the tab is place at the top?

Unfortunately until Qt 4.2 this is not possible yet (issue 146772), although according to issue 145880, "vertical tab bar layout" will be possible in Qt 4.3.

Just for fun, I found a very hackish way to make RoundedNorth for the tab bar (hence, the screenshot above). The trick is to find the tab bar using run-time introspection feature of Qt and then change the geometry manually. If I know in advance that there will be only one tab bar in my main window and there are only two dock widgets, this can be accomplished with a private slot like this:

void MainWindow::hackTabbedDocks()
{
 QDockWidget* topDock = d->historyDock;
 if( topDock->height() == 0)
   topDock = d->functionsDock;

 QList<QTabBar *> allTabs = findChildren<QTabBar *>();
 for(int ii = 0; ii < allTabs.size(); ++ii)
 {
   QTabBar* tab = allTabs[ii];
   if(tab->parentWidget() == this)
   {
     if(tab->geometry().top() > topDock->geometry().top())
     {
       tab->setShape( QTabBar::RoundedNorth );
       int h = tab->geometry().height();
       tab->move(tab->geometry().left(), topDock->geometry().top());
       topDock->move(topDock->geometry().left(), topDock->geometry().top()+h);
     }
     break;
   }
 }
}

I found out, I always need to call this slot twice so that it can work. To simplify, there two other slots which manage it:

void MainWindow::handleTabChange()
{
  QTimer::singleShot(0, this, SLOT(hack1()));
}

void MainWindow::hack1()
{
  hackTabbedDocks();
  QTimer::singleShot(100, this, SLOT(hackTabbedDocks()));
}

And I need to bind any signals which indicate that the tab bar has been relayouted, e.g. when a new tab is selected , when it is resized, etc, to handleTabChange slot above. For illustration purpose, let's just do the first. Of course, this can be done only when tab bar already exists. So, time for another silly slot:

void MainWindow::initHack()
{
  QList<QTabBar *> allTabs = findChildren<QTabBar *>();
  for(int ii = 0; ii < allTabs.size(); ++ii)
  {
    QTabBar* tab = allTabs[ii];
    if(tab->parentWidget() == this)
    {
      connect(tab, SIGNAL(currentChanged(int)), this, SLOT(handleTabChange()));
      break;
    }
  }
  handleTabChange();
}

which will be called from MainWindow's constructor by abusing QTimer once more:

  tabifyDockWidget( d->historyDock, d->functionsDock );
  QTimer::singleShot(0, this, SLOT(initHack()));

That's it!

The big disadvantage of this trick is obvious: flicker occurs everytime you do something with the docks, e.g. changing the tab. It will be quite annoying, but all of this is just a hack anyway. So was it fun? Yes. Useful? No.

(I guess the real "solution" is only waiting for the Trolls to implement it)



> Read More... | Digg This!

published by Ariya Hidayat on 2007-02-12 12:05:28 in the "coding" category
Ariya Hidayat

Consider the following simple operation, where k is integer and p is prime:

  int i = k % p;

Typically this will be assembled to (sorry, x86 only):

  mov  eax, k
  cdq
  idiv p

where the result is available in register EDX.

Such IDIV instruction has a latency of more than 40 cycles on Intel Pentium or AMD64 processor family. Hence, for optimization purposes, it is best to avoid integer division.

The above division/modulus operation can be avoided if the prime number p is chosen to be the Mersenne primes only, i.e there is a positive integer s such as p = 2s-1. In 32-bit range, there are Mersenne primes: 3, 7, 31, 127, 8191, 131071, 524287, and 2147483647.

The modulus operator with Mersenne prime can be simplified as:

  int i = (k & p) + (k >> s);
  return (i >= p) ? i - p : i;

One possible assembler implementation is as follows.

  ; assume edx = k, ebx = p, ecx = s
  ; result is in eax
  mov     eax, edx
  sar     edx, cl        ; k >> s
  and     eax, ebx       ; k & p
  add     eax, edx       ; eax is i = (k & p) + (k >> s)
  mov     edx, eax       ; edx is also i
  sub     edx, ebx       ; i - p
  cmp     eax, ebx       ; only if (i >= p)
  cmovge  eax, edx       ; then eax is (i-p)

Note that with the help of CMOVGE (6 cycles latency on Pentium 4), there is no need for real branching (which is expensive). Although the code is longer compared to the IDIV version, it executes much faster. Still faster if the range k is limited so that only a decrement operator is needed. Even faster of course if p is constant.

Last time I used this is for hash table (micro)optimization, because the number of stored items is known and I can live with a table whose size is a Mersenne prime. That's indeed a very special case only.

BTW this is off-topic, but thanks for those who mailed/texted me after this post. Nothing happened to me, I'm just fine. Those lines are from Keane's latest single (guess which one?), picked for no particular reason other that it's a good ballad.



> Read More... | Digg This!

published by nixcraft on 2006-12-19 01:12:28 in the "Open source coding" category
Vivek Gite Finally we have Ajax Secure Service Layer. From the project home page: aSSL is a library distributed under MIT License thats implements a technology similar to SSL without HTTPS. aSSL is composed from a file .js and a server component. Currently, the ASP and PHP components are ready. I’m developing Ruby and Java components and in the near [...]

> Read More... | Digg This!

published by nixcraft on 2006-12-16 03:13:27 in the "Open source coding" category
Vivek Gite According to wikipedia PageRank is a link analysis algorithm which assigns a numerical weighting to each element of a hyperlinked set of documents, such as the World Wide Web, with the purpose of “measuring” its relative importance within the set. The algorithm may be applied to any collection of entities with reciprocal quotations and references. The [...]

> Read More... | Digg This!

published by nixcraft on 2006-12-12 19:38:03 in the "Open source coding" category
Vivek Gite The Google Web Toolkit is a free toolkit by Google, as part of the Google Code initiative, to develop Ajax applications in the Java programming language. GWT supports rapid client/server development and debugging in any Java IDE From the project home page: Google Web Toolkit (GWT) is an open source Java software development framework that makes writing [...]

> Read More... | Digg This!

published by nixcraft on 2006-10-11 18:34:12 in the "Open source coding" category
Vivek Gite Discover what you should expect from an integrated development environment (IDE), and compare the cost and benefits of seven popular IDE choices for PHP. From the article: An IDE provides a one-stop shop for your coding work. An IDE contains an editor in which you can edit the code, debug the code, view your code in a [...]

> Read More... | Digg This!

published by nixcraft on 2006-10-09 20:02:31 in the "Open source coding" category
Vivek Gite CakePHP is a framework for PHP, based on Rails for Ruby. Its aim is to aid programming web applications. From the site: “Cake is a rapid development framework for PHP which uses commonly known design patterns like ActiveRecord, Association Data Mapping, Front Controller and MVC. Our primary goal is to provide a structured framework that [...]

> Read More... | Digg This!

published by linuxBot on 2006-07-26 08:13:44 in the "Open source coding" category
Vivek Gite PHP encryption for the common man (read as newbie) FTA, “…In this increasingly virtual online world, you have to be careful to protect your data. Learn the basics of encoding and encrypting important bits of information, such as passwords, credit card numbers, and even entire messages. Get an overview of what it means to encrypt and [...]

> Read More... | Digg This!