girish
Qt
Qtopia
KDE
Styles
Posted by girish
 in Qt, Qtopia, KDE, Styles
 on Tuesday, November 27, 2007 @ 16:37

This feels great. This post is an eight year old dream come true - I have always wanted to write an article titled “… for fun and profit” ever since I read the amazing phrack article :).

Qt Style Sheets makes it possible to style Qt widgets, we all know that. But, what if some user loved this Qt application and would love it even more, if only it had red push buttons (some users have strange fetishes)?

Qt 4.3’s well kept secret
In Qt 4.3, users can customize the style of any application without touching or recompiling the code. All Qt applications can take an external stylesheet using the -stylesheet command line switch. So, create a file called mystyle.qss containing “QPushButton { background: red; }”. Now start, any Qt applications as “qtapp -stylesheet mystyle.qss”. Sweeeet.

Theming Qt
So one can style widgets, but what if one wants to move things around. What if one wants the application to have a completely different layout. We have received many requests for supporting layouting in Qt Style Sheets, but did you know theming Qt applications is already possible?

So let’s see - we need a mechanism for the user to specify the layout. We can probably define our own XML format but it turns out Qt already has one and you use it all the time - .ui files. .ui file is nothing but the user interface described in XML. All we need is a mechanism to load these ui files on the fly.

Enter our hero QUiLoader. QUiLoader reads a ui file and gives you back a QWidget pointer. Ui files can be edited using Qt Designer, so you don’t need to create your own layout tool. In addition, QUiLoader::setWorkingDirectory allows creating ui files with external resources. That said, the main disadvantage is that theming this way requires you to modify your application.

I cooked up a media player that implements the above idea. You can add new themes in the themes/ folder. In addition to a layout(ui) file, the theme can also specify a style sheet. MediaPlayer can load these new themes with no recompilation.

Here’s the Classic theme that has the media controls on the bottom.
Classic Media Player

Here’s the Modern theme that has the media controls on the side.
Modern Media Player

To create a new theme,
* Unpack the source (with git history)
* qmake && make
* cp -R themes/classic themes/mytheme. At this point, mytheme and classic are identical.
* Edit file in mytheme/mediaplayer.ui using Designer
* Edit style sheet in mytheme/mediaplayer.qss using text editor
* Edit icons (play/stop/pause) under mytheme/.
* Notice how media player can support new layouts and styles with no recompilation at all.

Enjoy!

P.S: This is really a guest blog since I don’t work for Trolltech anymore :-) Please contact me at ramakrishnan dot girish at gmail, if you have any questions.

girish
Qt
KDE
Itemviews
Styles
Posted by girish
 in Qt, KDE, Itemviews, Styles
 on Thursday, November 01, 2007 @ 11:27

It all started as a small feature request - Adding style sheet support for Item views. I quickly found out that our default delegate, QItemDelegate, doesn’t use QStyle the way it is supposed to. Jens had faced the same problem when trying to provide native look and feel for Vista and ended up writing his own delegate. This is quite a limitation because currently authors of custom QStyles can customize the look of everything in Qt except item views.

So was born QStyledItemDelegate - The default delegate for Item views starting 4.4. To let that sink in - all our views now delegate painting to QStyledItemDelegate instead of QItemDelegate. QStyledItemDelegate prompty plays its part by delegating everything to QStyle :-) The cool thing is that this delegate uses the QStyle to determine the sizeHint, the layout of the text, indicators and icon. And of course, it paints everything through QStyle. Complete control to QStyle.

Jens has already incorporated this new feature into QWindowsVistaStyle. So, by default, your views will look all fancy in 4.4 like below:

vistatree2.png

We are unsure about how selection in table view must be handled. We are open to suggestions:

Chart example in vista style

On other platforms, they should exactly like before. If you had written your own delegate using QItemDelegate, it is completely unaffected by this change. If having to write a custom QStyle or a custom delegate sounds daunting, just use style sheets. Try something like this,

QTreeView::item {
    border: 1px solid #d9d9d9;
    border-top-color: transparent;
    border-bottom-color: transparent;
}

QTreeView::item:hover {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
    border: 1px solid #bfcde4;
}

QTreeView::item:selected {
    border: 1px solid #567dbc;
}

QTreeView::item:selected:active{
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);
}

QTreeView::item:selected:!active {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);
}

Here’s how it looks:

stylesheet-treeview.png

See Customizing QTreeView, Customizing QListView for more information.

We merged the new delegate into our main branch last week, so if use the latest snapshots, you already have it. If you have any specific requirements to styling of tree widgets, list views and tables in mind and are wondering if it is possible now using the new delegate, please leave behind a note!

girish
Qt
KDE
News
Posted by girish
 in Qt, KDE, News
 on Tuesday, September 18, 2007 @ 16:23

So here is more dramatic news following the Qtopia Phone is completely GPL announcement.

A couple of years back, we made a big move by Open Sourcing Qt for Windows. The Open Source edition of Qt/Windows supported only MinGW (and MinGW/MSYS starting Qt 4.3). The MSVC Makefile, project generator and the Integration was available only to commercial customers.

Today (a week back actually), we made another big move. We have decided to support Visual Studio Express with Qt/Windows Open Source - we are dual licensing the MSVC Makefile and project generator (Sorry, no VS Integration for Open Source users). Many thanks to our PM Eivind Thronsen for making this happen. So when will you get this? Well, if you had checked out the 4.3 snapshots, the generators have been available for about a week now. The mkspecs are on their way. We did schedule it for Qt 4.4 but some quick work by Marius and André will see this feature in Qt 4.3.2. Why make you wait for 5 more months to get hold of such goodness ;-) ?

The Visual Studio Express environment is just so much superior and easier to use for existing Windows developers compared to what MinGW provides. We foresee many of the Open Source projects switching to VS EE for development after this change. Video killed the radio star?

girish
Qt
KDE
Posted by girish
 in Qt, KDE
 on Monday, August 13, 2007 @ 16:11

After the mega feature enhancements that we added to Style Sheet in 4.3, we have been getting an awful lot of support requests and mails asking for examples to do all sorts of stuff. As a direct consequence, I have added tons of new documentation. What’s cool is that there is a separate example for styling each and every widget in the Customizing Specific Widgets section. Previously, the documentation was one flat html file. But it grew so big that our doc team has now split it up into separate pages. Trivia question: Which is the biggest documentation manual in Qt ? :).

My favorite bit is the Customizing TreeView example. One can style the tree view branches with 5 images. If you don’t like the tree view lines, you need only two. Here’s how it looks:
Tree View Branches

Comments/Suggestions? Leave a note behind.

girish
Qt
KDE
Posted by girish
 in Qt, KDE
 on Wednesday, August 08, 2007 @ 12:28

We just released 4.3.1, get it here.

We try to do a patch release every 1.5 months or so. This time around, given that most developers disappeared for summer vacation, getting 4.3.1 out was quite a challenge. But there, we/2 did it :-) But really, this post is just an excuse to show the picture of our brave support engineers (customers can get pretty aggressive at times). We have four support offices (click on the images and hover over the face to see their names):

The Beijing office support team
Beijing support team

The San Jose office support team
SJ Support team

The Oslo office support team
Oslo support team

The Brisbane office support team
—- watch out this space for Brisbane team picture —-

P.S. Yes, yes, we know about the difference in sex ratio between Oslo development team and Oslo support team. We (devs) are working on it - by joining support, of course ;-)

girish
Qt
News
Posted by girish
 in Qt, News
 on Tuesday, July 03, 2007 @ 10:28

Naren Karattup (our product manager) and I did a webinar two weeks back titled “Bringing C++ to Vista: Leveraging Your C++ Code-Base to Create Native Windows® Vista™ Applications”. If you missed it, you can now see it offline here. From the webcast link “We recommend the following operating systems: Windows XP SP2, and Mac OS X 10.4″. Sigh. Nevertheless, once you register, you should be able to see the slides.

girish
Qt
KDE
Posted by girish
 in Qt, KDE
 on Friday, June 29, 2007 @ 13:45

QSlider
I have been avoiding QSlider for sometime now. Sliding the QSlider would have been straightforward if the code was correct :). You need this teeny weeny patch against 4.3 (If you are using a week old 4.3 snapshot, you are good). Comments inline.


QSlider::groove:horizontal {
border: 1px solid #999999;
height: 8px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */
background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);
}
QSlider::handle:horizontal {
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f);
border: 1px solid #5c5c5c;
width: 18px;
margin: -2px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
border-radius: 3px;
}

Here’s how it looks:
Slider

If you require more control, play around with something like this (note that this is a vertical slider):
QSlider::groove:vertical {
background: red;
position: absolute; /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */
left: 4px; right: 4px;
}
QSlider::handle:vertical {
height: 10px;
background: green;
margin: 0 -4px; /* expand outside the groove */
}
QSlider::add-page:vertical {
background: white;
}
QSlider::sub-page:vertical {
background: pink;
}

QHeaderView
I thought I will have a go at something that looks like the header view in this plasmoid and show some advanced usage of the new pseudo states but I gotta run (and this posts been sitting as a draft for way too long).

QHeaderView::section {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #616161, stop: 0.5 #505050, stop: 0.6 #434343, stop:1 #656565);
color: white;
padding-left: 4px;
border: 1px solid #6c6c6c;
}

Here’s how it looks:
Header view

girish
Qt
Qtopia
KDE
Posted by girish
 in Qt, Qtopia, KDE
 on Friday, June 22, 2007 @ 06:56

Today we will look at the styling of one of the most complex widgets (when it comes to styling) in Qt - The QTabWidget. Fasten your seat belts so you don’t get blown away ;)

Comments inline.

QTabWidget::pane { /* The tab widget frame */
border-top: 2px solid #C2C7CB;
}
QTabWidget::tab-bar {
left: 5px; /* move to the right by 5px */
}
/* Style the tab using the tab sub-control. Note that it reads QTabBar _not_ QTabWidget */
QTabBar::tab {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);
border: 2px solid #C4C4C3;
border-bottom-color: #C2C7CB; /* same as the pane color */
border-top-left-radius: 4px;
border-top-right-radius: 4px;
min-width: 8ex;
padding: 2px;
}
QTabBar::tab:selected, QTabBar::tab:hover {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fafafa, stop: 0.4 #f4f4f4, stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);
}
QTabBar::tab:selected {
border-color: #9B9B9B;
border-bottom-color: #C2C7CB; /* same as pane color */
}
QTabBar::tab:!selected {
margin-top: 2px; /* make non-selected tabs look smaller */
}

This is how it looks:

Tab widget take one

“But but but… I want overlapping tabs!”. Negative margins to the rescue. Add this to the style sheet above.
/* IMPORTANT: 8< Add the code above here 8< */
QTabBar::tab:selected {
/* expand/overlap to the left and right by 4px */
margin-left: -4px;
margin-right: -4px;
}
QTabBar::tab:first:selected {
margin-left: 0; /* the first selected tab has nothing to overlap with on the left */
}
QTabBar::tab:last:selected {
margin-right: 0; /* the last selected tab has nothing to overlap with on the right */
}
QTabBar::tab:only-one {
margin: 0; /* if there is only one tab, we don't want overlapping margins */
}

Here’s how it looks:

Tab widget with overlapping tabs

You can also play around with fonts and colors. For example,
QTabBar::tab:selected { font: bold; color: green; }

You can move the tab bar to the center and adjust the pane using something like,
/* 8< remove the tab-bar rule and the margin-top rule in the first stylesheet */
QTabWidget::tab-bar { alignment: center; }
QTabWidget::pane { position: absolute; top: -0.5em; }

Tab Widget with centered tabs

Note that the above style sheets style assumes the tab bar to be at the top. You can use the :left, :right, :top, :bottom pseudo states for the position of the tab bar. There is also, :next-selected to indicate the next tab is selected, :previous-selected to indicate the previous tab is selected, :middle for a tab that is not the first or the last (same as :!first:!last). With some creative use of the above pseudo states, you can “merge” adjacent tab borders like in Plastique. And of course, you can use border-images to have the tabs curve in to the tab pane.

girish
Qt
KDE
Posted by girish
 in Qt, KDE
 on Tuesday, June 12, 2007 @ 17:17

Qt 4.3 Style Sheets, as you most likely know, introduces styling of most widgets. The documentation is a quite silent when it comes to providing “style templates” - templates that you can just copy/paste and get started with styling the widget. Today, I started creating templates for QProgressBar and QScrollBar. All this will become a part of 4.3.1 Style Sheet documentation.

QProgressBar
QProgressBar:horizontal {
border: 1px solid gray;
border-radius: 3px;
background: white;
padding: 1px;
}
QProgressBar::chunk:horizontal {
background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 green, stop: 1 white);
}

Here’s what you get:
Progress Bar with no chunk width

You say “Oh sweet, but I want WindowsXP like progress bars. And the label needs to be outside since its easier to read”. Yeah, sure.
QProgressBar:horizontal {
border: 1px solid gray;
border-radius: 3px;
background: white;
padding: 1px;
text-align: right;
margin-right: 4ex;
}
QProgressBar::chunk:horizontal {
background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 green, stop: 1 white);
margin-right: 2px; /* space */
width: 10px;
}

Right aligned text in progress bar

Note that you need set the height for vertical progress bars. You can use “:indeterminate” for indeterminate progress bars. And there’s a small bug which breaks text alignment (fixed in 4.3.1).

QScrollBar

QScrollBar:horizontal {
border: 2px solid green;
background: cyan;
height: 15px;
margin: 0px 20px 0 20px;
}
QScrollBar::handle:horizontal {
background: gray;
min-width: 20px;
}
QScrollBar::add-line:horizontal {
background: blue;
width: 20px;
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal {
background: white;
width: 20px;
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal {
width: 3px;
height: 3px;
background: pink;
}
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
background: none;
}

Here’s the awful but didactic screenshot:
Scroll bar

Style sheets are so powerful that you can actually place those add-line, remove-line button anywhere!
QScrollBar:horizontal {
border: 2px solid green;
background: cyan;
height: 15px;
margin: 0px 40px 0 0px;
}
QScrollBar::handle:horizontal {
background: gray;
min-width: 20px;
}
QScrollBar::add-line:horizontal {
background: blue;
width: 16px;
subcontrol-position: right;
subcontrol-origin: margin;
border: 2px solid black;
}
QScrollBar::sub-line:horizontal {
background: magenta;
width: 16px;
subcontrol-position: top right;
subcontrol-origin: margin;
border: 2px solid black;
position: absolute;
right: 20px;
}
QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal {
width: 3px;
height: 3px;
background: pink;
}
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
background: none;
}

Advanced styling of QScrollBar

For vertical scroll bars, you will need to replace width with height and use up-arrow and down-arrow. That said, remove those boring borders, slap in a few border-images, gradients and background color and it’s simple to create beautiful custom scroll bars.

girish
Qt
KDE
Posted by girish
 in Qt, KDE
 on Wednesday, June 06, 2007 @ 16:40

It looks like people have taken a deep liking to having line edits with a clear button. Like the one Aaron made. Since many seem to have missed that post, here’s my take on a QLineEdit with a clear button.

lineedit.h
lineedit.cpp

The code is fairly trivial. So, I won’t bother explaining. The clear button appears only when the line edit has text. Here’s how it looks,

Line edit with no text,
Line edit with no text

Line edit with some text (clear button appears)
Line edit with some text

Line edit with lotsa text (text doesn’t go underneath clear button)
Line edit with lots of text

Update: I got a question asking how to implement the search line edit with a menu, like in thunderbird. The clear button is a QToolButton. Just set a menu :) To move it to the left, just use padding-left and move the clear button appropriately.



© 2008 Nokia Corporation and/or its subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation in Finland and/or other countries worldwide.
All other trademarks are property of their respective owners.