cat /dev/maxilys

A glance in the mind of a KDE/Linux developer to see how ideas turn into code.

2006-11-28

KDE: Stating the obvious

Of course, I'm going to talk about Serenity's obvious changes. Last time, I really indulged myself in bragging about an internal change that has very few interest for the users. This time, let's see what you will see.

The oldest change I made is to introduct a new tree view style. I don't remember where I saw it apart that it was on a mockup somewhere in KDE's world. Any way, I fell in love. I called it "Modern". The colors are still a bit grey but not for long. What I really liked is the dotted list style of the expanded branches. That's very visible, very clean and nobody will complain about the solid lines. ;-)

Next, I made the sliders (the ones like in KMix volume control) look like arrowless sliders (the ones of the scrollbars), including the little arrows. I even had to draw tiny arrows. They also totally follow the colorscheme set for the scrollbars except that the arrows are less visible.

Then I touched again and again the progress bars patterns of which ones the drawing was less than optimal. I tried for a while to make patterns proportional to the height of the progress bar but it was useless. The difference in between a regular progress bar and a tiny one like in GIMP or at the bottom of Konqueror's window was very minimal. The only feature I've kept from my experiments is the introduction of a new shade of color. So, instead of being only bright-dark, the progress bar are bright-medium-dark.

New progress bar


If you find the colors odd or if you don't recognize the global style, it's just because there are two very obvious changes that I haven't spoken of yet.

I don't know which one is most obvious. So let's start with the oldest one: I wanted to introduce a third global style --I don't count "Flat" as a real one. I did like usual, I modified the main drawing routine of the Zen style. I don't know what I was trying to achieve but I know what I got: A very smooth new Zen style. The only thing I add to think about is the vertical scrollbars that were now ugly. That's simple, I just made my routine switch to a special design when the shape to draw is taller than wide and as much or narrower than a scrollbar. So you can still have tall buttons that won't look like scrollbars.

New Zen style


The second obvious change is everywhere: No more grey! In Serenity's README provided with the sources, --I wonder if somebody ever read it.-- I give the advice to add a little color to the blacks used in foreground, button label and text colors to fight against the invasion of the Little Greys. ;-) That's was a good start but not enough to my liking any more.

I changed the colorscheme I'm using right now ("Caloris Planitia") to be more orange than greyish orange but that's still not enough to explain the colors of the progress bar above.

For a few time, I had been using a special option to colorize the menu bar groove. It used to turn its color in something that you could call orange or at least brown. This morning, I got a flash: Why wouldn't I colorize everything that is so grey?

That's easier to do than it looks like. If everything is so grey that's because Serenity mixes the colors with the foreground to produce all its shades of color and that foreground is usually black. So, in Serenity's color factory, I hired lines of code to pour some color in the mix. Et voilĂ  ! You can keep on adding a very little color to the black texts but you won't be able to go as far as the color factory or the result will turn to ugly.

Now "Caloris Planitia" (which is the name of an area of the planet Mercury) burns on screen with all its shades of orange. Much closer from what I had in mind when I chose the name of the colorscheme!

All this led me to re-design the configuration dialog (again). I realized that spaces were good enough separators so I ditched all the utilitarian lines to keep only cosmetic ones. I like the result, especially the bold section titles. Now, I have to do the same with the window decoration configuration dialog for the sake of consistency but that will be very quick. I have mastered Qt Designer... when I pay attention to what I'm doing. ;-)

Next, I'll also propagate the new zen style to the windec, touch a little the layout so that the buttons don't walk on the (external) line when the border is reduced to 2 pixels. I already did a lot of work on it, especially to speed up the calculations to draw the frame, to select the colors of the buttons. It had become a kind of nightmare now that I added to possibility to choose the colorization tint of both the buttons and their symbol. I mean, you can now use either a color from the color list or the title blend color (for the buttons) or the title button color (for the symbols) instead of only their glow colors previously. That's how I managed to obtain the nice buttons on the dialogs hereabove. The Gay Pride is over, you can remove the Rainbow Flag from your title bar. ;-)

The rest are minor modifications that you'll discover in the changelog. If things go smoothly, maybe I'll release this week-end... for the world to find my new bugs. :-D

Labels: , ,

2006-11-24

KDE: Invisible Man

Two days after my nightmarish change of harddisk... I can go back to my usual business: Serenity. The version 1.5 has been out since November, the 6th. It's even a version 1.5.0 because I'm no professional surgeon. The major surgery didn't go as well as planned.

In fact, I was a bit over-zealous in my search and replace job and the colorschemes landed in a wrong directory. It was a very discreet bug on my system because without checking the timestamp, I couldn't see that the colorschemes came from a previous install.

Another also discreet bug that had been reported to me: the focus rectangles leaved traces when you moved icons in Konqueror's window. I just couldn't see it because those (ugly) focus rectangles had been disabled for months. I found them totally useless. My huge mouse cursor and the mouseover effect are more than enough to tell me which widget I'm using. However, those who prefer or need to use the keyboard can't disable the focus rectangles.

I looked very closely (with KMag) and I found that the corners of the rectangles were responsible for the traces. I just removed them and the traces were gone, without needing to resort to sharp corners. A question remains: Why did "they" need to add focus rectangles around the dragged and dropped icons?

While I was at it, I tried to do something about the rubber band of which the code part is just below the one of the focus rectangles. No much success so far, but I still have ideas. The currently plain rectangle is so boring!

These were the two last things I did. Before that, I did another major surgery. It's pretty much invisible, hence the title of the blog page.

First, let me explain something. To draw a button the serene way represents a lot of calculations, a lot of conditional code and if you don't optimize everything, you can generate a lot of temporary variables. Serenity wasn't actually slow but the drawing took some time crawling across my code. I already optimized the gradient routines, it was time to take care of the rest.

Here came the C++ and its classes. That's what I did. I created a new class: SereneShape(QRect, uint); Everytime I need to draw a button, a slider, a frame, whatever, I initiate a new instance of my class with the containing rectangle (QRect) and a variable (uint) which is a bitfield indicating where the round corners are, if any. Qt provides the rectangle --most of the time-- and Serenity contains pre-defined constants like Button_Alike, Square_Box, or else TopTab_Alike. No calculations here.

And I minimized the ones I had to do. The first step of the initialization asks Qt the coordinates of the rectangle, from which I get all the coordinates to draw a Square_Box. And that makes already 12 points. 2 points to draw each of the four border lines plus 1 point for each corner for the antialiasing.

The second and last step checks the uint variable to find the round corners and stores QPoint's, re-using already known coordinates and moving only one coordinate of the two affected border lines when needed. Along the process, it takes note of where it put things and count the number of available coordinates. A picture being worth a thousand words, here it is:

[Explicative image]


What you must understand from this picture is that when I store the values left, left+1, top and top+1, to go from a square corner to a "round" one, the only new values I need are left+2 and top+2. I do this for the four corners and the drawing routine can go on.

For the moment, all it did was:
SereneShape shape(rect, flags);


Now, it can use the accessors to retrieve all the needed values. To make things even faster, I unfolded my code because, most of the time, the four borders are needed (only the tabs have three borders only), the four corners are either round or square all together (only the tabs or the pressed menubar entries are half-rounded), and making a test at each corner to know if the aliased corners must be drawn alphablended is a massive waste of time.

For example, to draw a solid frame with or without rounded corners with alphablend corners (like around an edit field or a tab page), all the code that is actually executed is:

p->setPen(contour);
if ((flags&Square_Box) == Square_Box)
{
p->drawLine( shape.topLeft(), shape.topRight() );
p->drawLine( shape.leftTop(), shape.leftBottom() );
p->drawLine( shape.rightTop(), shape.rightBottom() );
p->drawLine( shape.bottomLeft(), shape.bottomRight() );
}
//
// The else branch is here.
//
for (int i = 1 ; i <= shape.cornerPixels() ; i++)
{
p->drawPoint( shape.cornerPoint(i) );
}
if (flags & Draw_AlphaBlend)
{
for (int i = 1 ; i <= shape.aliasedPixels() ; i++)
{
renderPixel(p, shape.aliasedPoint(i), contour);
}
}
//
// The else branch is here.
//


That's all. To limit even more the accesses to the class, I used QPoint's everywhere.

I'm very partial --Hey! That's my code.-- but to my eyes, the gain in speed is very visible. The reason behind this result despite the class overhead is: less temporary variables and very less conditional code to eat your CPU cycles like a hungry shark.

And if you think that I'm bragging about my code... you're right! I'm very proud of my code. That's the first class that I ever write from scratch in C++ without taking inspiration from anywhere... despite the fact that I still haven't really learned C++ and it worked right from the beginning. I amazed myself. :-D

Well, I'd like to keep on bragging but I have other things to do. ;-) I'll talk about the other visible changes in Serenity style and windec next time.

Labels: , ,

2006-11-21

Linux: Moving out...

My new disk had been lying around for, well, at least two weeks. I just couldn't find the strength or the desire to copy my system on it. I thought it would be boring to death... In text mode with nothing much to do but watch the wonderful animations of 'htop'... I was wrong!

It was a nightmare! Now, I hate GRUB. It's totally abstruse. Its mini-CLI is a joke, its help doesn't help anybody. Sorry, but I have to put the blame on something else than my own stupidity that played --maybe-- the main role in this nightmare. ;-)

Any way, here's how it moved out: I switched to runlevel 3 so that nothing messes with me with opened files, lock files, whatever, all over the partitions. I mounted the freshly partitionned new disk and copied everything, folder by folder with 'cp -dpR /this /over/there'. I did it this way in order to still have something to do instead of waiting forever that 'cp' finishes its job with absolutely nothing to do. 'htop' has very limited animation capabilities. ;-)

That was the fastest part. Then I tried with YaST to install a new boot loader. Shutdown. I removed the old disk and plugged the new one. Re-boot and...
GRUB

Keyboard dead. Nothing else to do but press the reset button. Oh... Happiness...

I re-booted in rescue mode with the first CD of my SuSE. I intended to let GRUB install itself. I'm used to the abstruse UNIX tools but GRUB is the champion in this category. How I am supposed to guess that the partitions are labelled "(hdX,Y)" if GRUB doesn't say it anywhere, not even in its manpage... which is inaccessible any way because 'man' isn't available in rescue mode. Maybe in the infopages... but that's definitely not a reflex by me.

I simply wasn't able to do anything with GRUB! Period.

Shutdown. Switch the disks. Re-boot. Google!

Ha! (hd0,4) is my /boot partition.

Shutdown. Switch the disks. Re-boot. Rescue mode.

'grub'... What are those "stage1", "stage2" and "stage1.5"?

Shutdown. Switch the disks. Re-boot. Google!

'grub-install --root-directory=/boot /dev/hda' said Google. This time, I didn't come back empty-handed.

Shutdown. Switch the disks. Re-boot. Rescue mode.

'grub-install...' Are you doing anything? Yes? No? Maybe? CTRL+C!

'grub'
GRUB>

Back to square one! Tried this... Tried that... "Succeeded" said GRUB.

Shutdown. Re-boot.
GRUB

Keyboard dead. Reset. Re-boot. Rescue mode.

'grub'
GRUB>

Looked like familiar... I was almost feeling at home. Tried this... Tried that... "Succeeded" said GRUB... but I wouldn't believe if it told me that the sky is blue.

Shutdown. Re-boot.

Miracle! It ran... in text mode. "/blah/blah/message" not found. Not good... And effectively. No boot possible. Partition not found.
GRUB>

Shutdown. Re-boot. Rescue mode.

'joe /mnt/grub/menu.lst' (Where is Nano or Pico when you need it?)

All this was a bit my fault. I didn't pay attention to the fact that on my old disk the swap partition was the first while I put it in second on the new disk.

Shutdown. Re-boot.

Second miracle! It ran in graphic mode. It even booted! Until...

"fsck failed" and needed to be run manually on a partition (not root).

I fsck'ed almost everything. No error. WTF?

'pico /etc/fstab'

My bad! If GRUB doesn't like to find unexpected things on the partitions, 'fsck' is even stricter! So, I swapped two lines. /boot is hda5 and swap is hda6.

Shutdown. Re-boot.

Nobody complained any more. I reached the login and... Oh boy! The xdm login screen made my eyes bleed.

No KDE, not even Gnome, no nothing! /opt is empty! Cold sweat... Didn't I copy it? Yes, I did! I could remember it! WTF?

'init 3 ; pico /etc/fstab'

Before this new disk, I already added a new disk, move /home onto it and moved /opt on the partition where /home was. That's what "fstab" said... But what it did was to mount a now empty partition over the definitively not empty /opt.

I banged my head against a few walls. ;-) I corrected my mistake... and another less important one, copied the partition I forgot.

'init 5'

The new disk is hanging out of the case on a little carton box, the old disk is plugged where the CD-ROM usually is. Whatever? It works!

Next time, I'll know what to pay attention at and the remedy to all the possible errors. And if I ever forget, this blog will be here to remind me.

I've moved out. :-D

2006-11-01

KDE: Major surgery

Last time I wanted to transplant a ".UI"-file-based configuration dialog to Serenity style. I did it... and so much more!

First, now Serenity is a single archive. That's the major surgery I did. I don't know any program that can handle makefiles and that kind of things so I just took the archive of another theme with a style and a window decoration: Polyester. By the way, thanks to Marco for all the hard work he did so I could just slip my feet in his shoes. That's pretty much what I did. I removed Polyester's sources and put Serenity's ones instead. The rest is pure white magic. I invoked the goddess Kate and all her minions --Control+F, Control+R, Control+C and Control+V. After some MP3 chantings, Kate granted my wish: "Serenity will now and forever be one archive". :-D

Since Polyester has ".ui" files for both the style and the window decoration configuration dialogs, Serenity acquired this feature along the magical process. Now, when you say to your Konsole "Configure, make and install!", you get the total Serenity at once. Of course, you can still install only what you want but does "a half serenity" actually mean something?

Now that I can use Qt designer instead of having to code everything by hand, I don't hesitate to turn the options upside down. And I needed it! I re-arranged the configuration dialog in three columns so that it didn't become bigger than its calling parent when I added more options.

I already described a few of these options in my previous posts. Here are a few new ones that are very noticeable: The button-alike framing of the sub-menus arrows can now be deactivated. Since I felt the tiny arrows weren't visible enough when I remove the framing, I then used bigger arrows so that the sub-menu indicators have always approximatively the same size. I blended the big arrows just a little with the menu background and the result is really nice. The second thing I did for the menus is to add a new groove style: a very subtle gradient with round corners. But I'm not sure I'll keep it. The result isn't... hmmm... optimal when the menubar is cut into several lines.

By the way, while I'm speaking about gradients: I changed Serenity's own gradient routines to use only int's instead of float's. That was meant to accelerate them. I don't know if it did any real good but I feel a kind of acceleration. The power of auto-suggestion, maybe? ;-)

Something that should be also immediately visible: the tabs. I removed the button-alike looks of the active tab. I haven't use them since I introduced the nicer gradient look and I couldn't stand them when I tried them recently. Then I could take care of the inactive tabs. Somebody wrote that he couldn't get used to the "big grey bar" look. Maybe that was true that the inactive tabs were, well, too solid. I changed them to use a vertical gradient instead. It's nice. It's "lighter". To complete the look, I gave the possibility to separate the inactive tabs so that they don't look like a bar. A picture is worth a thousand words, so look for yourself. This is the new style configuration dialog. Look very closely and you will see the new smooth junction of the active tab with the panel below it. (And yes, the very light touch of grey below the yellowish bar is the menu groove.) That's pretty much all I did for the style.

For once, I worked a little more on the window decoration. That's very visible in the new configuration dialog. (Don't look for the "intentionally left blank" spaces, I managed to get rid of them. They made me laugh.) I however didn't succeed in giving much more room to the preview. (I tried very hard but the dialog apparently refuses to shrink beyond a certain point.) Any way, I haven't finished yet.

Look at the second page. Do you see the option "Colorized symbols"? That's the first step. I've already removed one type of buttons from the dedicated combobox but thanks to this option, the number of button types got multiplied by two. I will removed some more button types but I will also add a new switch: "Colorized buttons" that will multiply the remaining number of types by two, once more. With the last option I keep in my sleeve, it will be possible to change of button type every day and not to see twice the same in a month... or two months if you count the solid titlebar background switch that also has some effect on the buttons. Totally useless, especially that some combinations of options will clean the titlebar up to the point of having nothing left but the caption, but totally indispensable too. ;-)

Well, time to go to bed. It's already tomorrow... as always!

Labels: , ,