This forum has been archived. All content is frozen. Please use KDE Discuss instead.

[Widget Style] Qt Quick Controls

Tags: None
(comma "," separated)
Tuukka
Registered Member
Posts
69
Karma
0
OS
Very nice! I think we've found a good balance in most aspects. Once we can try this on real applications it'll probably be easier to do some more adjustments with sizes and so on. I'm very happy that we'll have a QtQuick controls style that matches the QtWidget style so that people can start writing native looking QML UIs for KDE apps as soon as the Frameworks come out. Just some random observations:

There's also a style for TableView but it's not included in the demo app?

BreezeStyle.qml seems to import QtGraphicalEffects and QtTest even though they don't seem to be used. Might be a good idea to remove the imports to minimize the number of packages required to run the demo.

It's a good idea to try the style with very large fonts as well (that are needed for high DPI screens). The button size will adjust to the size of the label, whereas text fields will stay fixed at 32pix. In general this is no problem, but currenctly there is a bug in the editable ComboBox, whose height will be determined by the label (even if it's invisible) but it will still be drawn 32pix high. This can be fixed by adding anchors.fill: parent to the background:
[code]
TextFieldBackground {
visible: control.editable
anchors.fill: parent
}[/code]
User avatar
Heiko Tietze
Registered Member
Posts
593
Karma
0
OS
Although the filled check box is a stunning graphical effect I'm afraid it diminishes usability. Using a check mark, or the like, differentiates the control from radio button on a further perceptual dimension than only the shape.
Sogatori
Registered Member
Posts
209
Karma
1
OS

Re: [Widget Style] Qt Quick Controls

Mon Apr 21, 2014 12:14 pm
Great progess everyone! It looks really nice already.
I only think that some elements could use an ever so light gradient, too. Like the buttons.

I have questions though:
It seems that the VDG has descided to embrace qtcurve, does that mean that the development of the GTK+3 engine will be continued again? Currently only oxygen is able to give gtk+3 applications a somewhat native look.
Tuukka
Registered Member
Posts
69
Karma
0
OS
Sogatori wrote:Great progess everyone! It looks really nice already.
I only think that some elements could use an ever so light gradient, too. Like the buttons.

The buttons already have a gradient. It's so subtle that its hard to see but it does make it more button-like compared to a completely flat color.
Sogatori
Registered Member
Posts
209
Karma
1
OS
Tuukka wrote:
Sogatori wrote:Great progess everyone! It looks really nice already.
I only think that some elements could use an ever so light gradient, too. Like the buttons.

The buttons already have a gradient. It's so subtle that its hard to see but it does make it more button-like compared to a completely flat color.

Oh yes, I ment to say that these controls could use the same kind of slight gradient as used on the buttons. Words are hard :| My appologies
User avatar
alake
Registered Member
Posts
591
Karma
3
OS
Tuukka wrote:There's also a style for TableView but it's not included in the demo app?

Oh yes that was just an oversight, just uncomment the 4th tab in Breeze.qml to see that. :-)

Tuukka wrote:BreezeStyle.qml seems to import QtGraphicalEffects and QtTest even though they don't seem to be used. Might be a good idea to remove the imports to minimize the number of packages required to run the demo.

It's a good idea to try the style with very large fonts as well (that are needed for high DPI screens). The button size will adjust to the size of the label, whereas text fields will stay fixed at 32pix. In general this is no problem, but currenctly there is a bug in the editable ComboBox, whose height will be determined by the label (even if it's invisible) but it will still be drawn 32pix high. This can be fixed by adding anchors.fill: parent to the background:
Code: Select all
           
TextFieldBackground {
                visible: control.editable
                anchors.fill: parent
            }


Great catch thanks! If you see anything else like this that we can fix and tidy up, please share. As I get more info on packaging for use as a QtQuick system style, the wider community will certainly be grateful for your help finding and fixing issues like these. Of course if anyone wants to jump in and help with any of this, please feel free. :-)
User avatar
alake
Registered Member
Posts
591
Karma
3
OS
Sogatori wrote:It seems that the VDG has descided to embrace qtcurve, does that mean that the development of the GTK+3 engine will be continued again? Currently only oxygen is able to give gtk+3 applications a somewhat native look.


Yeah, this exercise was primarily to produce a UI controls design target that happens to be directly usable for QtQuick-based UIs. QtCurve is just a low workload option we've suggested to get some relatively cheap visual unity for non Qt-Quick based UIs. I know I would certainly welcome a C++ QStyle or GTK+ 3 or any other implementation of this design if someone was willing to do it. :-)
User avatar
colomar
Registered Member
Posts
947
Karma
2
OS
Heiko Tietze wrote:Although the filled check box is a stunning graphical effect I'm afraid it diminishes usability. Using a check mark, or the like, differentiates the control from radio button on a further perceptual dimension than only the shape.


While that is certainly true, we don't know if the negative effect on usability is significant. In Andrew's preliminary user test, it didn't seem to be. We can easily repeat the test with a larger sample (if everyone here asks just five people, we'd already have a good sample) and see whether they can easily enough distinguish checkbox from radio button.
Good design needs to strike the right balance between aesthetics and usability, so if we can show empirically that the negative effect is negligible, we could still accept it for the gain in aesthetics. If we find that some people have considerable problems with the distinction, we should think again.
User avatar
alake
Registered Member
Posts
591
Karma
3
OS
Hey, so permit me a silly indulgence to recognize what we were able to accomplish in such a short time:



;D
Tuukka
Registered Member
Posts
69
Karma
0
OS
alake wrote:Hey, so permit me a silly indulgence to recognize what we were able to accomplish in such a short time:
;D

Nice presentation :). Good material for a blog entry perhaps?

Oh yes, I ment to say that these controls could use the same kind of slight gradient as used on the buttons. Words are hard :| My appologies

Perhaps the slider handle could have the same gradient as the buttons..?

Since we are preparing for the first release, I thought ColorUtils.js could use some cleanup. Because we always use color objects (not strings) it was easy to greatly simplify the functions. Also I got rid of blendColors2() because it has the same purpose as Qt.lighter(). It doesn't always behave exactly the same way but I found parameters for Qt.lighter() that give practically the same button gradients as before. Here's the output of 'git diff':
Code: Select all
diff --git a/BreezeStyle.qml b/BreezeStyle.qml
index b4663f4..ea7883d 100644
--- a/BreezeStyle.qml
+++ b/BreezeStyle.qml
@@ -61,7 +61,7 @@ Style {
                 implicitHeight: parent.height - 2
                 implicitWidth: parent.width - 2
                 radius: 2.5
-                color: ColorUtils.fullColorString(sysPalette.shadow, 0.2)
+                color: ColorUtils.adjustAlpha(sysPalette.shadow, 0.2)
                 transform: Translate {x: 1; y: 1}
             }
             Rectangle {
@@ -75,13 +75,13 @@ Style {
                 gradient: Gradient {
                     GradientStop {
                         position: 0.0
-                        color: control.activeFocus ? ColorUtils.shadeColor2(sysPalette.highlight, 0.1) :
-                                                     ColorUtils.shadeColor2(sysPalette.button, 0.05)
+                        color: control.activeFocus ? Qt.lighter(sysPalette.highlight, 1.03) :
+                                                     Qt.lighter(sysPalette.button, 1.006)
                     }
                     GradientStop {
                         position: 1.0
-                        color: control.activeFocus ? ColorUtils.shadeColor2(sysPalette.highlight, -0.07) :
-                                                     ColorUtils.shadeColor2(sysPalette.button, -0.02)
+                        color: control.activeFocus ? Qt.darker(sysPalette.highlight, 1.07) :
+                                                     Qt.darker(sysPalette.button, 1.02)
                     }
                 }
                 transform: Translate {x: control.pressed ? 1 : 0; y: control.pressed ? 1 : 0}
@@ -118,7 +118,7 @@ Style {
                 implicitHeight: parent.height - 8
                 implicitWidth: parent.width - 8
                 radius: 3
-                color: ColorUtils.fullColorString(sysPalette.shadow, 0.15)
+                color: ColorUtils.adjustAlpha(sysPalette.shadow, 0.15)
                 transform: Translate {x: 1; y: 1}
             }
             Rectangle {
@@ -238,7 +238,7 @@ Style {
                 implicitHeight: parent.height - 2
                 implicitWidth: parent.width - 2
                 radius: 2.5
-                color: ColorUtils.fullColorString(sysPalette.shadow, 0.2)
+                color: ColorUtils.adjustAlpha(sysPalette.shadow, 0.2)
                 transform: Translate {x: 1; y: 1}
             }
             Rectangle {
@@ -253,13 +253,13 @@ Style {
                 gradient: Gradient {
                     GradientStop {
                         position: 0.0
-                        color: control.activeFocus ? ColorUtils.shadeColor2(sysPalette.highlight, 0.1) :
-                                                     ColorUtils.shadeColor2(sysPalette.button, 0.05)
+                        color: control.activeFocus ? Qt.lighter(sysPalette.highlight, 1.03) :
+                                                     Qt.lighter(sysPalette.button, 1.006)
                     }
                     GradientStop {
                         position: 1.0
-                        color: control.activeFocus ? ColorUtils.shadeColor2(sysPalette.highlight, -0.07) :
-                                                     ColorUtils.shadeColor2(sysPalette.button, -0.02)
+                        color: control.activeFocus ? Qt.darker(sysPalette.highlight, 1.07) :
+                                                     Qt.darker(sysPalette.button, 1.02)
                     }
                 }
                 transform: Translate {x: control.pressed ? 1 : 0; y: control.pressed ? 1 : 0}
@@ -309,7 +309,7 @@ Style {
                 visible: !control.indeterminate
                 anchors.fill: parent
                 anchors.margins: 5
-                color: ColorUtils.fullColorString(sysPalette.buttonText, 0.3)
+                color: ColorUtils.adjustAlpha(sysPalette.buttonText, 0.3)
                 radius: 3
             }
         }
@@ -377,7 +377,7 @@ Style {
                 height: 20
                 width: 20
                 radius: 11
-                color: ColorUtils.fullColorString(sysPalette.shadow, 0.15)
+                color: ColorUtils.adjustAlpha(sysPalette.shadow, 0.15)
                 transform: Translate { x: 1; y: 1 }
             }
             Rectangle {
@@ -492,12 +492,12 @@ Style {
         }
         scrollBarBackground: ScrollBar {
             anchors.centerIn: parent
-            barColor: ColorUtils.fullColorString(sysPalette.windowText, 0.3)
+            barColor: ColorUtils.adjustAlpha(sysPalette.windowText, 0.3)
         }
         handle: ScrollBar {
             barColor: styleData.hovered ? sysPalette.button :
                                           control.activeFocus ? sysPalette.highlight :
-                                                                ColorUtils.fullColorString(sysPalette.text, 0.5)
+                                                                ColorUtils.adjustAlpha(sysPalette.text, 0.5)
             barBorder.color: sysPalette.highlight
             barBorder.width: styleData.hovered ? 2 : 0
         }
@@ -526,7 +526,7 @@ Style {
             Rectangle {
                 anchors.fill: parent
                 anchors.margins: 5
-                color: ColorUtils.fullColorString(sysPalette.windowText, 0.3)
+                color: ColorUtils.adjustAlpha(sysPalette.windowText, 0.3)
                 radius: 3
             }
 
@@ -553,7 +553,7 @@ Style {
                 height: 20
                 width: 20
                 radius: 10
-                color: ColorUtils.fullColorString(sysPalette.shadow, 0.15)
+                color: ColorUtils.adjustAlpha(sysPalette.shadow, 0.15)
                 transform: Translate { x: 0; y: 0 }
             }
 
@@ -607,7 +607,7 @@ Style {
             implicitWidth: 48
             implicitHeight: 24
             radius: 12
-            color: control.checked ? ColorUtils.fullColorString(sysPalette.highlight, 1) : ColorUtils.fullColorString(sysPalette.buttonText, 0.3)
+            color: control.checked ? ColorUtils.adjustAlpha(sysPalette.highlight, 1) : ColorUtils.adjustAlpha(sysPalette.buttonText, 0.3)
         }
 
         handle: Rectangle {
@@ -624,7 +624,7 @@ Style {
                 radius: 11
                 color: sysPalette.window
                 border.width: control.activeFocus ? 2 : 1
-                border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.fullColorString(sysPalette.buttonText, 0.1)
+                border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.adjustAlpha(sysPalette.buttonText, 0.1)
            }
         }
     }
@@ -636,19 +636,19 @@ Style {
             implicitHeight: 300
             implicitWidth: 300
             border.width: control.activeFocus ? 2 : 1
-            border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.fullColorString(sysPalette.windowText, 0.3)
+            border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.adjustAlpha(sysPalette.windowText, 0.3)
             radius: 2.5
             color: sysPalette.base
         }
         scrollBarBackground: ScrollBar {
             color: sysPalette.base
             anchors.centerIn: parent
-            barColor: ColorUtils.fullColorString(sysPalette.windowText, 0.3)
+            barColor: ColorUtils.adjustAlpha(sysPalette.windowText, 0.3)
         }
         handle: ScrollBar {
             barColor: styleData.hovered ? sysPalette.button :
                                           control.activeFocus ? sysPalette.highlight :
-                                                                ColorUtils.fullColorString(sysPalette.text, 0.5)
+                                                                ColorUtils.adjustAlpha(sysPalette.text, 0.5)
             barBorder.color: sysPalette.highlight
             barBorder.width: styleData.hovered ? 2 : 0
         }
@@ -694,7 +694,7 @@ Style {
                 anchors.bottom: parent.bottom
                 anchors.bottomMargin: 0
                 anchors.horizontalCenter: parent.horizontalCenter
-                color: ColorUtils.fullColorString(sysPalette.windowText, 0.1)
+                color: ColorUtils.adjustAlpha(sysPalette.windowText, 0.1)
             }
             Rectangle {
                 width: 1
@@ -703,7 +703,7 @@ Style {
                 anchors.verticalCenter: parent.verticalCenter
                 anchors.topMargin: 1
                 anchors.bottomMargin: 1
-                color: ColorUtils.fullColorString(sysPalette.windowText, 0.2)
+                color: ColorUtils.adjustAlpha(sysPalette.windowText, 0.2)
             }
         }
         rowDelegate: Rectangle {
@@ -723,7 +723,7 @@ Style {
         tabsAlignment: Qt.AlignHCenter
         tab: Rectangle {
             color: styleData.selected ? ColorUtils.blendColors(sysPalette.window, sysPalette.base, 0.3) :
-                                        styleData.hovered ? ColorUtils.fullColorString(sysPalette.highlight, 0.2) : ColorUtils.fullColorString(sysPalette.windowText, 0.2)
+                                        styleData.hovered ? ColorUtils.adjustAlpha(sysPalette.highlight, 0.2) : ColorUtils.adjustAlpha(sysPalette.windowText, 0.2)
             implicitWidth: Math.max(text.implicitWidth + 8, 80)
             implicitHeight: Math.max(text.implicitHeight + 8, 28)
             border.color: ColorUtils.blendColors(sysPalette.window, sysPalette.windowText, 0.25)
@@ -771,19 +771,19 @@ Style {
             implicitHeight: 300
             implicitWidth: 300
             border.width: control.activeFocus ? 2 : 1
-            border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.fullColorString(sysPalette.windowText, 0.3)
+            border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.adjustAlpha(sysPalette.windowText, 0.3)
             radius: 2.5
             color: sysPalette.base
         }
         scrollBarBackground: ScrollBar {
             color: sysPalette.base
             anchors.centerIn: parent
-            barColor: ColorUtils.fullColorString(sysPalette.windowText, 0.3)
+            barColor: ColorUtils.adjustAlpha(sysPalette.windowText, 0.3)
         }
         handle: ScrollBar {
             barColor: styleData.hovered ? sysPalette.button :
                                           control.activeFocus ? sysPalette.highlight :
-                                                                ColorUtils.fullColorString(sysPalette.text, 0.5)
+                                                                ColorUtils.adjustAlpha(sysPalette.text, 0.5)
             barBorder.color: sysPalette.highlight
             barBorder.width: styleData.hovered ? 2 : 0
         }
@@ -840,7 +840,7 @@ Style {
                 implicitWidth: parent.width - 2
                 implicitHeight: parent.height - 2
                 border.width: 1
-                border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.fullColorString(sysPalette.windowText, 0.25)
+                border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.adjustAlpha(sysPalette.windowText, 0.25)
                 radius: 2.5
                 color: control.pressed || control.checked ? sysPalette.highlight : sysPalette.button
             }
diff --git a/ColorUtils.js b/ColorUtils.js
index c4b3450..9618358 100644
--- a/ColorUtils.js
+++ b/ColorUtils.js
@@ -1,33 +1,9 @@
 //  Color manipulation utilities
 
-//  creates color value from hue, saturation, brightness, alpha
-function hsba(h, s, b, a) {
-    var lightness = (2 - s)*b;
-    var satHSL = s*b/((lightness <= 1) ? lightness : 2 - lightness);
-    lightness /= 2;
-    return Qt.hsla(h, satHSL, lightness, a);
-}
-
-//  creates a full color string from color value and alpha[0..1], e.g. "#FF00FF00"
-function fullColorString(clr, a) {
-    return "#" + ((Math.ceil(a*255) + 256).toString(16).substr(1, 2) +
-            clr.toString().substr(1, 6)).toUpperCase();
-}
-
-//  extracts integer color channel value [0..255] from color value
-function getChannelStr(clr, channelIdx) {
-    return parseInt(clr.toString().substr(channelIdx*2 + 1, 2), 16);
-}
-
-function shadeColor2(clr, percent) {
-    var color = clr.toString();
-    var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
-    return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
+function adjustAlpha(clr, a) {
+   return Qt.rgba(clr.r, clr.g, clr.b, a);
 }
 
 function blendColors(clr0, clr1, p) {
-    var c0 = clr0.toString();
-    var c1 = clr1.toString();
-    var f=parseInt(c0.slice(1),16),t=parseInt(c1.slice(1),16),R1=f>>16,G1=f>>8&0x00FF,B1=f&0x0000FF,R2=t>>16,G2=t>>8&0x00FF,B2=t&0x0000FF;
-    return "#"+(0x1000000+(Math.round((R2-R1)*p)+R1)*0x10000+(Math.round((G2-G1)*p)+G1)*0x100+(Math.round((B2-B1)*p)+B1)).toString(16).slice(1);
-}
+   return Qt.tint(clr0, adjustAlpha(clr1, p));
+}
\ No newline at end of file
diff --git a/ScrollBar.qml b/ScrollBar.qml
index 223b256..b680367 100644
--- a/ScrollBar.qml
+++ b/ScrollBar.qml
@@ -31,7 +31,7 @@ Rectangle {
         anchors.centerIn: __barFill
         width: 20
         height: 20
-        color: ColorUtils.fullColorString(sysPalette.windowText, 0.15)
+        color: ColorUtils.adjustAlpha(sysPalette.windowText, 0.15)
         radius: width/2
         transform: Translate {
             x: 0
diff --git a/TextFieldBackground.qml b/TextFieldBackground.qml
index 0d77624..9dc3ae9 100644
--- a/TextFieldBackground.qml
+++ b/TextFieldBackground.qml
@@ -7,7 +7,7 @@ Rectangle {
     implicitHeight: 32
     implicitWidth: 148
     border.width: control.activeFocus ? 2 : 1
-    border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.fullColorString(sysPalette.windowText, 0.3)
+    border.color: (control.activeFocus || control.hovered) ? sysPalette.highlight : ColorUtils.adjustAlpha(sysPalette.windowText, 0.3)
     radius: 2.5
     color: sysPalette.base
 }
User avatar
Heiko Tietze
Registered Member
Posts
593
Karma
0
OS
colomar wrote:
Heiko Tietze wrote:Although the filled check box is a stunning graphical effect I'm afraid it diminishes usability. Using a check mark, or the like, differentiates the control from radio button on a further perceptual dimension than only the shape.

While that is certainly true, we don't know if the negative effect on usability is significant....

All of us will perceive the difference between round corners of 2px and 5px, or the like. But using a program efficiently you don't want to take attention on this tiny distinction. However, go ahead, if I'm the only one with concerns. It's very easy to change this aspect of the theme later, I guess.
cloose
Registered Member
Posts
10
Karma
0
Heiko Tietze wrote:
colomar wrote:
Heiko Tietze wrote:Although the filled check box is a stunning graphical effect I'm afraid it diminishes usability. Using a check mark, or the like, differentiates the control from radio button on a further perceptual dimension than only the shape.

While that is certainly true, we don't know if the negative effect on usability is significant....

All of us will perceive the difference between round corners of 2px and 5px, or the like. But using a program efficiently you don't want to take attention on this tiny distinction. However, go ahead, if I'm the only one with concerns. It's very easy to change this aspect of the theme later, I guess.


I really like this new widget style. Great work!

But I agree with Heiko that the difference between radio button and checkbox is too small. Would it destroy the aesthetics, if you would add a checkmark inside the box?

Crude example proving that I'm not a designer :) :

Image
mutlu
Registered Member
Posts
75
Karma
0
OS
alake wrote:
  • Indeterminate progress bar design
Image

Looks wonderful! Small suggestion: how about making the length of the two differently colored 'bar sections' in the indeterminate progress bar unequal? I would be curious to see what it looks like, if either the dark blue or the light blue bar section would be very short, so much that it is as long as high (i.e. a square). Could you give it a try?
User avatar
GreatEmerald
Registered Member
Posts
84
Karma
0
OS

Re: [Widget Style] Qt Quick Controls

Tue Apr 22, 2014 12:01 pm
Yay, we got our rounding! :D
I agree that the tabs are pretty much the only thing left. I thought the previous suggestions for the tabs were neat, but if you think they don't work well... Hmm... How about a lighter shade of grey? Or maybe even the same colour, but put the button-like gradient on the active tab? That, with the lack of the bottom border, may be enough to differentiate it.

Another thing to remember is to change the highlight method on the text elements so it wouldn't just be a blue underline.

I also think that the current checkbox design is good enough as it is. I know that several game UIs use such a checkbox design and it doesn't confuse anyone.
User avatar
alake
Registered Member
Posts
591
Karma
3
OS
Tuukka wrote:Since we are preparing for the first release, I thought ColorUtils.js could use some cleanup. Because we always use color objects (not strings) it was easy to greatly simplify the functions.


Excellent! Thanks Tuukka. I'll incorporate these changes in the next few days.

I just wanted to quickly clarify for others here again that "release" here is about release of the design to the developers and packagers for incorporation when they see fit. Plasma 2 is already well past the feature freeze date, so no one should reasonably expect this in the initial Plasma 2 release in June Plasma 2014.06 release.

Oh and I'm still looking for a set of extras hand to do up some QtCurve settings that mimics this as closely as possible.

Thanks again!


Bookmarks



Who is online

Registered users: Bing [Bot], claydoh, Google [Bot], markhm, rblackwell, sethaaaa, Sogou [Bot], Yahoo [Bot]