summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Bache-Wiig <jens.bache-wiig@nokia.com>2011-02-21 10:52:17 +0100
committerJens Bache-Wiig <jens.bache-wiig@nokia.com>2011-02-21 11:03:49 +0100
commit88f140ddd7f634ad4411f4d16cae51a93eb856b7 (patch)
tree97918777eb4be0e9da103ca431f43211e4454544
parent9917d1d23cced9f3f91ec8a0504c2942e72adfc7 (diff)
downloadqtquickcontrols-88f140ddd7f634ad4411f4d16cae51a93eb856b7.tar.gz
Added widgets
-rw-r--r--components/Button.qml27
-rw-r--r--components/ButtonRow.qml5
-rw-r--r--components/CheckBox.qml26
-rw-r--r--components/ChoiceList.qml52
-rw-r--r--components/GroupBox.qml27
-rw-r--r--components/ProgressBar.qml31
-rw-r--r--components/RadioButton.qml26
-rw-r--r--components/ScrollArea.qml103
-rw-r--r--components/ScrollBar.qml109
-rw-r--r--components/Slider.qml31
-rw-r--r--components/SpinBox.qml91
-rw-r--r--components/Switch.qml22
-rw-r--r--components/Tab.qml7
-rw-r--r--components/TabBar.qml90
-rw-r--r--components/TabFrame.qml72
-rw-r--r--components/TextArea.qml44
-rw-r--r--components/TextField.qml52
-rw-r--r--components/TextScrollArea.qml31
-rw-r--r--components/ToolBar.qml12
-rw-r--r--components/ToolButton.qml18
-rw-r--r--components/custom/BasicButton.qml44
-rw-r--r--components/custom/BusyIndicator.qml27
-rw-r--r--components/custom/Button.qml39
-rw-r--r--components/custom/ButtonBlock.qml216
-rw-r--r--components/custom/ButtonColumn.qml44
-rw-r--r--components/custom/ButtonGroup.js127
-rw-r--r--components/custom/ButtonRow.qml43
-rw-r--r--components/custom/CheckBox.qml49
-rw-r--r--components/custom/ChoiceList.qml85
-rw-r--r--components/custom/ProgressBar.qml80
-rw-r--r--components/custom/RadioButton.qml13
-rw-r--r--components/custom/ScrollDecorator.qml20
-rw-r--r--components/custom/ScrollIndicator.qml56
-rw-r--r--components/custom/Slider.qml291
-rw-r--r--components/custom/SpinBox.qml142
-rw-r--r--components/custom/Switch.qml85
-rw-r--r--components/custom/TextArea.qml156
-rw-r--r--components/custom/TextField.qml196
-rw-r--r--components/custom/behaviors/ButtonBehavior.qml31
-rw-r--r--components/custom/behaviors/ModalPopupBehavior.qml90
-rw-r--r--components/custom/behaviors/TextEditMouseBehavior.qml266
-rw-r--r--components/custom/components.pro49
-rw-r--r--components/custom/private/ChoiceListPopup.qml269
-rw-r--r--components/custom/qmldir17
-rw-r--r--components/custom/styles/default/BasicButtonStyle.qml8
-rw-r--r--components/custom/styles/default/BusyIndicatorStyle.qml21
-rw-r--r--components/custom/styles/default/ButtonBlockStyle.qml77
-rw-r--r--components/custom/styles/default/ButtonStyle.qml102
-rw-r--r--components/custom/styles/default/CheckBoxStyle.qml34
-rw-r--r--components/custom/styles/default/ChoiceListStyle.qml100
-rw-r--r--components/custom/styles/default/ProgressBarStyle.qml142
-rw-r--r--components/custom/styles/default/RadioButtonStyle.qml34
-rw-r--r--components/custom/styles/default/ScrollIndicatorStyle.qml18
-rw-r--r--components/custom/styles/default/SliderStyle.qml110
-rw-r--r--components/custom/styles/default/SpinBoxStyle.qml73
-rw-r--r--components/custom/styles/default/SwitchStyle.qml71
-rw-r--r--components/custom/styles/default/TextFieldStyle.qml41
-rw-r--r--components/custom/styles/default/images/button_normal.pngbin0 -> 877 bytes
-rw-r--r--components/custom/styles/default/images/button_pressed.pngbin0 -> 803 bytes
-rw-r--r--components/custom/styles/default/images/buttongroup_h_normal.pngbin0 -> 482 bytes
-rw-r--r--components/custom/styles/default/images/buttongroup_h_pressed.pngbin0 -> 386 bytes
-rw-r--r--components/custom/styles/default/images/checkbox_check.pngbin0 -> 557 bytes
-rw-r--r--components/custom/styles/default/images/handle.pngbin0 -> 1529 bytes
-rw-r--r--components/custom/styles/default/images/lineedit_normal.pngbin0 -> 794 bytes
-rw-r--r--components/custom/styles/default/images/progress-bar-background.pngbin0 -> 484 bytes
-rw-r--r--components/custom/styles/default/images/progress-bar-bar.pngbin0 -> 548 bytes
-rw-r--r--components/custom/styles/default/images/progressbar_fill.pngbin0 -> 992 bytes
-rw-r--r--components/custom/styles/default/images/progressbar_groove.pngbin0 -> 492 bytes
-rw-r--r--components/custom/styles/default/images/progressbar_indeterminate.pngbin0 -> 1152 bytes
-rw-r--r--components/custom/styles/default/images/progressbar_overlay.pngbin0 -> 284 bytes
-rw-r--r--components/custom/styles/default/images/qt-logo.pngbin0 -> 954 bytes
-rw-r--r--components/custom/styles/default/images/radiobutton_check.pngbin0 -> 1331 bytes
-rw-r--r--components/custom/styles/default/images/radiobutton_check_white.pngbin0 -> 1310 bytes
-rw-r--r--components/custom/styles/default/images/radiobutton_normal.pngbin0 -> 1752 bytes
-rw-r--r--components/custom/styles/default/images/slider-background.pngbin0 -> 293 bytes
-rw-r--r--components/custom/styles/default/images/slider-handle-active.pngbin0 -> 506 bytes
-rw-r--r--components/custom/styles/default/images/slider-handle.pngbin0 -> 516 bytes
-rw-r--r--components/custom/styles/default/images/slider.pngbin0 -> 617 bytes
-rw-r--r--components/custom/styles/default/images/spinbox_down.pngbin0 -> 347 bytes
-rw-r--r--components/custom/styles/default/images/spinbox_up.pngbin0 -> 341 bytes
-rw-r--r--components/custom/styles/default/images/spinner.pngbin0 -> 2629 bytes
-rw-r--r--components/custom/styles/default/images/switch_normal.pngbin0 -> 834 bytes
-rw-r--r--components/custom/styles/default/images/switch_pressed.pngbin0 -> 709 bytes
-rw-r--r--components/custom/styles/default/tools/ColorConverter.qml59
-rw-r--r--components/custom/visuals/AdjoiningCorner.qml31
-rw-r--r--components/custom/visuals/AdjoiningVisual.qml50
-rw-r--r--components/images/folder_new.pngbin0 -> 1199 bytes
-rw-r--r--components/plugin/qmldir1
-rw-r--r--components/src.pro2
-rw-r--r--components/styleitem/qstyleitem.cpp547
-rw-r--r--components/styleitem/qstyleitem.h197
-rw-r--r--components/styleitem/qstyleplugin.cpp83
-rw-r--r--components/styleitem/qstyleplugin.h55
-rw-r--r--components/styleitem/styleitem.pro38
-rw-r--r--src/Button.qml27
-rw-r--r--src/ButtonRow.qml5
-rw-r--r--src/CheckBox.qml26
-rw-r--r--src/ChoiceList.qml52
-rw-r--r--src/GroupBox.qml27
-rw-r--r--src/ProgressBar.qml31
-rw-r--r--src/RadioButton.qml26
-rw-r--r--src/ScrollArea.qml103
-rw-r--r--src/ScrollBar.qml109
-rw-r--r--src/Slider.qml31
-rw-r--r--src/SpinBox.qml91
-rw-r--r--src/Switch.qml22
-rw-r--r--src/Tab.qml7
-rw-r--r--src/TabBar.qml90
-rw-r--r--src/TabFrame.qml72
-rw-r--r--src/TextArea.qml44
-rw-r--r--src/TextField.qml52
-rw-r--r--src/TextScrollArea.qml31
-rw-r--r--src/ToolBar.qml12
-rw-r--r--src/ToolButton.qml18
-rw-r--r--src/components/ButtonGroup.js127
-rw-r--r--src/components/components.pro49
-rw-r--r--src/components/qmldir17
-rw-r--r--src/images/folder_new.pngbin0 -> 1199 bytes
-rw-r--r--src/plugin/qmldir1
-rw-r--r--src/styleitem/styleitem.pro38
-rw-r--r--src/widgets/Button.qml27
-rw-r--r--src/widgets/ButtonRow.qml5
-rw-r--r--src/widgets/CheckBox.qml26
-rw-r--r--src/widgets/ChoiceList.qml52
-rw-r--r--src/widgets/GroupBox.qml27
-rw-r--r--src/widgets/ProgressBar.qml31
-rw-r--r--src/widgets/RadioButton.qml26
-rw-r--r--src/widgets/ScrollArea.qml103
-rw-r--r--src/widgets/ScrollBar.qml109
-rw-r--r--src/widgets/Slider.qml31
-rw-r--r--src/widgets/SpinBox.qml91
-rw-r--r--src/widgets/Switch.qml22
-rw-r--r--src/widgets/Tab.qml7
-rw-r--r--src/widgets/TabBar.qml90
-rw-r--r--src/widgets/TabFrame.qml72
-rw-r--r--src/widgets/TextArea.qml44
-rw-r--r--src/widgets/TextField.qml52
-rw-r--r--src/widgets/TextScrollArea.qml31
-rw-r--r--src/widgets/ToolBar.qml12
-rw-r--r--src/widgets/ToolButton.qml18
140 files changed, 7189 insertions, 0 deletions
diff --git a/components/Button.qml b/components/Button.qml
new file mode 100644
index 00000000..496d37df
--- /dev/null
+++ b/components/Button.qml
@@ -0,0 +1,27 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Button {
+ id:button
+
+ property int buttonHeight: Math.max(22, styleitem.sizeFromContents(100, 6).height)
+ height: buttonHeight
+
+ QStyleItem {
+ id:styleitem
+ elementType:"button"
+ sunken: pressed
+ raised: !pressed
+ hover: containsMouse
+ enabled:button.enabled
+ text:button.text
+ }
+
+ background:
+ QStyleBackground {
+ style:styleitem
+ anchors.fill:parent
+ }
+}
+
diff --git a/components/ButtonRow.qml b/components/ButtonRow.qml
new file mode 100644
index 00000000..623c5f44
--- /dev/null
+++ b/components/ButtonRow.qml
@@ -0,0 +1,5 @@
+import QtQuick 1.0
+import "../../../components" as Components
+
+Components.ButtonRow {
+}
diff --git a/components/CheckBox.qml b/components/CheckBox.qml
new file mode 100644
index 00000000..632dce2d
--- /dev/null
+++ b/components/CheckBox.qml
@@ -0,0 +1,26 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jb : Size should not depend on background, we should make it consistent
+
+Components.CheckBox{
+ id:checkbox
+ property variant text
+ width:100
+ height:18
+
+ background: QStyleBackground {
+ id:styleitem
+ style:QStyleItem {
+ elementType:"checkbox"
+ sunken:pressed
+ on:checked || pressed
+ hover:containsMouse
+ text:checkbox.text
+ enabled:checkbox.enabled
+ }
+ }
+ checkmark: null
+}
+
diff --git a/components/ChoiceList.qml b/components/ChoiceList.qml
new file mode 100644
index 00000000..5015fbef
--- /dev/null
+++ b/components/ChoiceList.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.ChoiceList {
+ id:choicelist
+
+ property int buttonHeight: buttonitem.sizeFromContents(100, 18).height
+ QStyleItem { id:buttonitem; elementType:"combobox" }
+ height: buttonHeight
+ topMargin:4
+ bottomMargin:4
+
+ QStyleItem {
+ id:styleitem
+ elementType: "combobox"
+ sunken: pressed
+ raised: !pressed
+ hover: containsMouse
+ enabled:choicelist.enabled
+ }
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: styleitem
+ }
+
+ listItem: Item {
+ id:item
+
+ height:22
+ anchors.left:parent.left
+ width:choicelist.width
+ QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType: "menuitem"
+ text: choicelist.model.get(index).text
+ selected: highlighted
+ }
+ }
+ }
+
+ popupFrame: QStyleBackground {
+ property int fw: styleitem.pixelMetric("menupanelwidth");
+ anchors.leftMargin: styleitem.pixelMetric("menuhmargin") + fw
+ anchors.rightMargin: styleitem.pixelMetric("menuhmargin") + fw
+ anchors.topMargin: styleitem.pixelMetric("menuvmargin") + fw
+ anchors.bottomMargin: styleitem.pixelMetric("menuvmargin") + fw
+ style:QStyleItem{elementType:"menu"}
+ }
+}
diff --git a/components/GroupBox.qml b/components/GroupBox.qml
new file mode 100644
index 00000000..0d45810d
--- /dev/null
+++ b/components/GroupBox.qml
@@ -0,0 +1,27 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Item {
+ width:200
+ height:46
+
+ property alias text: styleitem.text
+ default property alias children: content.children
+ property bool checkable: false
+
+ QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ id:styleitem
+ elementType:"groupbox"
+ }
+
+ Item {
+ id:content
+ anchors.topMargin:22
+ anchors.leftMargin:6
+ anchors.fill:parent
+ }
+ }
+}
diff --git a/components/ProgressBar.qml b/components/ProgressBar.qml
new file mode 100644
index 00000000..bf29bcac
--- /dev/null
+++ b/components/ProgressBar.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.ProgressBar {
+ id:progressbar
+
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 15).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ height: buttonHeight
+
+ background: QStyleBackground{
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType:"progressbar"
+
+ // XXX: since desktop uses int instead of real, the progressbar
+ // range [0..1] must be stretched to a good precision
+ property int factor : 1000000
+
+ value: progressbar.value * factor
+ minimum: indeterminate ? 0 : progressbar.minimumValue * factor
+ maximum: indeterminate ? 0 : progressbar.maximumValue * factor
+ enabled: progressbar.enabled
+ }
+ }
+ indeterminateProgress:null
+ progress: null
+}
+
diff --git a/components/RadioButton.qml b/components/RadioButton.qml
new file mode 100644
index 00000000..3c2c3e54
--- /dev/null
+++ b/components/RadioButton.qml
@@ -0,0 +1,26 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jb : Size should not depend on background, we should make it consistent
+
+Components.RadioButton{
+ id:radiobutton
+ property variant text
+ width:110
+ height:18
+
+ background: QStyleBackground {
+
+ style: QStyleItem{
+ elementType:"radiobutton"
+ sunken:pressed
+ on:checked || pressed
+ hover:containsMouse
+ text:radiobutton.text
+ enabled:radiobutton.enabled
+ }
+ }
+ checkmark: null
+}
+
diff --git a/components/ScrollArea.qml b/components/ScrollArea.qml
new file mode 100644
index 00000000..3a904dde
--- /dev/null
+++ b/components/ScrollArea.qml
@@ -0,0 +1,103 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+FocusScope {
+ id:scrollarea
+ width: 100
+ height: 100
+
+ property int contentMargin: 1
+ property int __scrollbarExtent : styleitem.pixelMetric("scrollbarExtent");
+ property int frameWidth: styleitem.pixelMetric("defaultframewidth");
+ property int contentHeight : content.childrenRect.height
+ property int contentWidth: content.childrenRect.width
+ property alias color: flickable.color
+ property bool frame: true
+ property bool highlightOnFocus: false
+
+ default property alias children: content.children
+
+ property int contentY
+ property int contentX
+
+ property bool frameAroundContents: styleitem.styleHint("framearoundcontents")
+
+ onContentYChanged: {
+ vscrollbar.value = contentY
+ }
+
+ onContentXChanged: {
+ hscrollbar.value = contentX
+ }
+
+ QStyleBackground {
+ style: QStyleItem{
+ id:styleitem
+ elementType: frame ? "frame" : ""
+ sunken: true
+ }
+ anchors.fill: parent
+ anchors.rightMargin: (frameAroundContents && vscrollbar.visible) ? vscrollbar.width + 4 : -frameWidth
+ anchors.bottomMargin: (frameAroundContents && hscrollbar.visible) ? hscrollbar.height + 4 : -frameWidth
+ anchors.topMargin: (frameAroundContents && hscrollbar.visible) ? hscrollbar.height + 4 : -frameWidth
+
+ Rectangle {
+ id:flickable
+ color: "transparent"
+ anchors.fill: parent
+ anchors.margins: frame ? 2 : 0
+ clip: true
+
+ Item {
+ id: docmargins
+ anchors.fill:parent
+ anchors.margins:contentMargin
+ Item {
+ id: content
+ x: -scrollarea.contentX
+ y: -scrollarea.contentY
+ }
+ }
+ }
+ }
+
+ ScrollBar {
+ id: hscrollbar
+ orientation: Qt.Horizontal
+ visible: contentWidth > flickable.width
+ maximumValue: contentWidth > flickable.width ? scrollarea.contentWidth - flickable.width : 0
+ minimumValue: 0
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: { return (frame ? 1 : 0) + ( vscrollbar.visible ? __scrollbarExtent : 0) }
+ onValueChanged: contentX = value
+ }
+
+ ScrollBar {
+ id: vscrollbar
+ orientation: Qt.Vertical
+ visible: contentHeight > flickable.height
+ maximumValue: contentHeight > flickable.height ? scrollarea.contentHeight - flickable.height : 0
+ minimumValue: 0
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: { return (frame ? 1 : 0) + (hscrollbar.visible ? __scrollbarExtent : 0) }
+ onValueChanged: contentY = value
+ }
+
+ QStyleBackground {
+ z:2
+ anchors.fill:parent
+ anchors.margins:-2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ visible: highlightOnFocus && parent.activeFocus && styleitem.styleHint("focuswidget")
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+}
diff --git a/components/ScrollBar.qml b/components/ScrollBar.qml
new file mode 100644
index 00000000..ea822b62
--- /dev/null
+++ b/components/ScrollBar.qml
@@ -0,0 +1,109 @@
+import QtQuick 1.1
+import "../../../components" as Components
+import "../plugin"
+
+MouseArea {
+ id:scrollbar
+ property int __scrollbarExtent : styleitem.pixelMetric("scrollbarExtent");
+ implicitWidth:orientation == Qt.Horizontal ? 200 : __scrollbarExtent;
+ implicitHeight:orientation == Qt.Horizontal ? __scrollbarExtent : 200
+
+ property int orientation : Qt.Horizontal
+ property alias minimumValue: slider.minimumValue
+ property alias maximumValue: slider.maximumValue
+ property alias value: slider.value
+
+ property bool upPressed;
+ property bool downPressed;
+ property bool __autoincrement: false
+
+ // Update hover item
+ onEntered: styleitem.activeControl = bgitem.hitTest(mouseX, mouseY)
+ onExited: styleitem.activeControl = "none"
+ onMouseXChanged: styleitem.activeControl = bgitem.hitTest(mouseX, mouseY)
+ hoverEnabled:true
+
+ Timer { running: upPressed || downPressed; interval: 350 ; onTriggered: __autoincrement = true }
+ Timer { running: __autoincrement; interval: 60 ; repeat: true ;
+ onTriggered: upPressed ? decrement() : increment() }
+
+ onPressed: {
+ var control = bgitem.hitTest(mouseX,mouseY)
+ if (control == "up") {
+ upPressed = true
+ } else if (control == "down") {
+ downPressed = true
+ }
+ }
+
+ onReleased: {
+ __autoincrement = false;
+ if (upPressed) {
+ upPressed = false;
+ decrement()
+ } else if (downPressed) {
+ increment()
+ downPressed = false;
+ }
+ }
+
+ function increment() {
+ value += 30
+ if (value > maximumValue)
+ value = maximumValue
+ }
+
+ function decrement() {
+ value -= 30
+ if (value < minimumValue)
+ value = minimumValue
+ }
+
+ QStyleBackground {
+ id:bgitem
+ anchors.fill:parent
+ style: QStyleItem {
+ id:styleitem
+ elementType: "scrollbar"
+ hover: activeControl != "none"
+ activeControl: "none"
+ sunken: upPressed | downPressed
+ minimum: slider.minimumValue
+ maximum: slider.maximumValue
+ value: slider.value
+ horizontal: orientation == Qt.Horizontal
+ enabled: parent.enabled
+ }
+ }
+
+ property variant handleRect
+ function updateHandle() {
+ handleRect = bgitem.subControlRect("handle")
+ var grooveRect = bgitem.subControlRect("groove");
+ var extra = 0
+ if (orientation == Qt.Vertical) {
+ slider.anchors.topMargin = grooveRect.y + extra
+ slider.anchors.bottomMargin = height - grooveRect.y - grooveRect.height + extra
+ } else {
+ slider.anchors.leftMargin = grooveRect.x + extra
+ slider.anchors.rightMargin = width - grooveRect.x - grooveRect.width + extra
+ }
+ }
+
+ onValueChanged: updateHandle()
+ onMaximumValueChanged: updateHandle()
+ onMinimumValueChanged: updateHandle()
+ Component.onCompleted: updateHandle()
+ Components.Slider {
+ id:slider
+ anchors.fill:parent
+ orientation:scrollbar.orientation
+ leftMargin: (orientation === Qt.Horizontal) ? handleRect.width/2 : handleRect.height/2
+ rightMargin:leftMargin
+ handle: Item { width:orientation == Qt.Vertical ? handleRect.height : handleRect.width;
+ height:orientation == Qt.Vertical ? handleRect.width : handleRect.height}
+ groove:null
+ valueIndicator:null
+ inverted:orientation != Qt.Horizontal
+ }
+}
diff --git a/components/Slider.qml b/components/Slider.qml
new file mode 100644
index 00000000..c6b9c915
--- /dev/null
+++ b/components/Slider.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jens: ContainsMouse breaks drag functionality
+
+Components.Slider{
+ id:slider
+ minimumWidth:200
+
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 15).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ height: buttonHeight
+
+ groove: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"slider"
+ sunken: pressed
+ maximum:slider.maximumValue
+ minimum:slider.minimumValue
+ value:slider.value
+ horizontal:slider.orientation == Qt.Horizontal
+ enabled:slider.enabled
+ }
+ }
+
+ handle: null
+ valueIndicator: null
+}
diff --git a/components/SpinBox.qml b/components/SpinBox.qml
new file mode 100644
index 00000000..2db428ce
--- /dev/null
+++ b/components/SpinBox.qml
@@ -0,0 +1,91 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.SpinBox {
+ id:spinbox
+
+ property variant __upRect;
+ property variant __downRect;
+ property int __margin: (height -16)/2
+
+ // Align height with button
+ topMargin:__margin
+ bottomMargin:__margin
+
+ property int buttonHeight: edititem.sizeFromContents(100, 20).height
+ QStyleItem { id:edititem; elementType:"edit" }
+ height: buttonHeight
+ clip:false
+
+ background:
+ Item {
+ anchors.fill: parent
+ property variant __editRect
+
+ Rectangle {
+ id:editBackground
+ x: __editRect.x - 1
+ y: __editRect.y
+ width: __editRect.width
+ height: __editRect.height
+ }
+
+ Item {
+ id:focusFrame
+ anchors.fill: editBackground
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -6
+ anchors.leftMargin: -5
+ anchors.fill: parent
+ visible:spinbox.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+
+ function updateRect() {
+ __upRect = spinboxbg.subControlRect("up");
+ __downRect = spinboxbg.subControlRect("down");
+ __editRect = spinboxbg.subControlRect("edit");
+ }
+
+ Component.onCompleted:updateRect()
+ onWidthChanged:updateRect()
+ onHeightChanged:updateRect()
+
+ QStyleBackground {
+ id:spinboxbg
+ anchors.fill:parent
+ style: QStyleItem {
+ id: styleitem
+ elementType: "spinbox"
+ sunken: downPressed | upPressed
+ hover: containsMouse
+ focus: spinbox.activeFocus
+ enabled: spinbox.enabled
+ value: (upPressed? 1 : 0) |
+ (downPressed== 1 ? 1<<1 : 0) |
+ (upEnabled? (1<<2) : 0) |
+ (downEnabled == 1 ? (1<<3) : 0)
+ }
+ }
+ }
+
+ up: Item {
+ x: __upRect.x
+ y: __upRect.y
+ width: __upRect.width
+ height: __upRect.height
+ }
+
+ down: Item {
+ x: __downRect.x
+ y: __downRect.y
+ width: __downRect.width
+ height: __downRect.height
+ }
+}
diff --git a/components/Switch.qml b/components/Switch.qml
new file mode 100644
index 00000000..b82817c9
--- /dev/null
+++ b/components/Switch.qml
@@ -0,0 +1,22 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Switch {
+ id:widget
+ minimumWidth:100
+ minimumHeight:30
+
+ groove:QStyleItem {
+ elementType:"edit"
+ sunken: true
+ }
+
+ handle: QStyleItem {
+ elementType:"button"
+ width:widget.width/2
+ height:widget.height-4
+ hover:containsMouse
+ }
+}
+
diff --git a/components/Tab.qml b/components/Tab.qml
new file mode 100644
index 00000000..e258185b
--- /dev/null
+++ b/components/Tab.qml
@@ -0,0 +1,7 @@
+import Qt 4.7
+
+Item {
+ id:tab
+ anchors.fill:parent
+ property string title
+}
diff --git a/components/TabBar.qml b/components/TabBar.qml
new file mode 100644
index 00000000..2d891256
--- /dev/null
+++ b/components/TabBar.qml
@@ -0,0 +1,90 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+
+Item {
+ id: tabbar
+ property int tabHeight: styleitem.sizeFromContents(100, 24).height
+ height: tabHeight
+
+ property Item tabFrame
+ onTabFrameChanged:parent = tabFrame
+ visible: tabFrame ? tabFrame.tabsVisible : true
+ property int __overlap : styleitem.pixelMetric("tabvshift");
+ property string position: tabFrame ? tabFrame.position : "North"
+ property string tabBarAlignment: styleitem.styleHint("tabbaralignment");
+ property int tabOverlap: styleitem.pixelMetric("taboverlap");
+
+ function tab(index) {
+ for (var i = 0; i < tabrow.children.length; ++i) {
+ if (tabrow.children[i].tabindex == index) {
+ return tabrow.children[i]
+ }
+ }
+ return null;
+ }
+
+ QStyleItem {
+ id:styleitem
+ elementType: "tab"
+ text: "generic"
+ }
+
+ Row {
+ id:tabrow
+ states:
+ State {
+ when: tabBarAlignment == "center"
+ name: "centered"
+ AnchorChanges {
+ target:tabrow
+ anchors.horizontalCenter: tabbar.horizontalCenter
+ }
+ }
+ Repeater {
+ id:repeater
+ model: tabFrame ? tabFrame.tabs.length : null
+ delegate: Item {
+ id:tab
+ property int tabindex: index
+ property bool selected : tabFrame.current == index
+ width: textitem.width + 42
+ height: tabHeight
+ z: selected ? 1 : -1
+
+ QStyleBackground {
+ style: QStyleItem {
+ id:style
+ elementType: "tab"
+ selected: tab.selected
+ text: tabbar.position
+
+ activeControl: tabFrame.count == 1 ?
+ "only" :
+ index == 0 ? "beginning" :
+ index == tabFrame.count-1 ? "end" : "middle"
+ }
+ anchors.leftMargin: -tabOverlap + (style.text == "North" && (style.activeControl == "middle" || style.activeControl == "end")
+ && tab.selected ? -__overlap : 0)
+
+ anchors.rightMargin: -tabOverlap + (style.text == "North" && (style.activeControl == "middle" || style.activeControl == "beginning")
+ && tab.selected ? -__overlap : 0)
+ anchors.fill:parent
+ }
+
+ Text {
+ id:textitem
+ anchors.centerIn:parent
+ text: tabFrame.tabs[index].title
+ elide: Text.ElideRight
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: tabFrame.current = index
+ }
+ }
+ }
+ }
+}
diff --git a/components/TabFrame.qml b/components/TabFrame.qml
new file mode 100644
index 00000000..01896e75
--- /dev/null
+++ b/components/TabFrame.qml
@@ -0,0 +1,72 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Item{
+ id: tabWidget
+ width:100
+ height:100
+ property TabBar tabbar
+ property int current: 0
+ property int count: stack.children.length
+ property bool frame:true
+ property bool tabsVisible: true
+ property string position: "North"
+ default property alias tabs : stack.children
+
+ onCurrentChanged: __setOpacities()
+ Component.onCompleted: __setOpacities()
+ onTabbarChanged: {
+ tabbar.tabFrame = tabWidget
+ tabbar.anchors.top = tabWidget.top
+ tabbar.anchors.left = tabWidget.left
+ tabbar.anchors.right = tabWidget.right
+ }
+
+ property int __baseOverlap : style.pixelMetric("tabbaseoverlap");
+ function __setOpacities() {
+ for (var i = 0; i < stack.children.length; ++i) {
+ stack.children[i].opacity = (i == current ? 1 : 0)
+ }
+ }
+
+ QStyleBackground {
+ id: frame
+ z:-1
+ style: QStyleItem {
+ id:style
+ elementType: "tabframe"
+ text: position
+ value: tabbar && tabsVisible && tabbar.tab(current) ? tabbar.tab(current).x : 0
+ minimum: tabbar && tabsVisible && tabbar.tab(current) ? tabbar.tab(current).width : 0
+ }
+ anchors.fill:parent
+ Item {
+ id:stack
+ anchors.fill:parent
+ anchors.margins: frame ? 2 : 0
+ }
+ anchors.topMargin: tabbar && tabsVisible && position == "North" ? tabbar.height - __baseOverlap : 0
+
+ states: [
+ State {
+ name: "South"
+ when: position == "South" && tabbar!= undefined
+ PropertyChanges {
+ target: frame
+ anchors.topMargin: 0
+ anchors.bottomMargin: tabbar ? tabbar.height - __baseOverlap: 0
+ }
+ PropertyChanges {
+ target: tabbar
+ anchors.topMargin: -__baseOverlap
+ }
+ AnchorChanges {
+ target: tabbar
+ anchors.top: frame.bottom
+ anchors.bottom: undefined
+ }
+ }
+ ]
+ }
+}
diff --git a/components/TextArea.qml b/components/TextArea.qml
new file mode 100644
index 00000000..93ad8f3d
--- /dev/null
+++ b/components/TextArea.qml
@@ -0,0 +1,44 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.TextArea {
+ id:textarea
+ leftMargin:12
+ rightMargin:12
+ minimumWidth:200
+ desktopBehavior:true
+ placeholderText:""
+ clip:false
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 14).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ minimumHeight: buttonHeight
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"edit"
+ sunken:true
+ focus:textarea.activeFocus
+ }
+ }
+
+ Item{
+ id:focusFrame
+ anchors.fill: textarea
+ parent:textarea.parent
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ anchors.fill: parent
+ visible:textarea.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+}
diff --git a/components/TextField.qml b/components/TextField.qml
new file mode 100644
index 00000000..260584e9
--- /dev/null
+++ b/components/TextField.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.TextField {
+ id:textfield
+ minimumWidth:200
+ desktopBehavior:true
+ placeholderText:""
+ topMargin:2
+ bottomMargin:2
+ leftMargin:6
+ rightMargin:6
+ width:200
+ height: editItem.sizeFromContents(100, 20).height
+ clip:false
+
+ QStyleItem {
+ id:editItem
+ elementType:"edit"
+ sunken:true
+ focus:textfield.activeFocus
+ hover:containsMouse
+ }
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"edit"
+ sunken:true
+ focus:textfield.activeFocus
+ }
+ }
+
+ Item{
+ id:focusFrame
+ anchors.fill: textfield
+ parent:textfield
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ anchors.fill: parent
+ visible:textfield.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+}
diff --git a/components/TextScrollArea.qml b/components/TextScrollArea.qml
new file mode 100644
index 00000000..2a7deab6
--- /dev/null
+++ b/components/TextScrollArea.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+ScrollArea {
+ id:area
+ color: "white"
+ width: 280
+ height: 120
+ contentWidth: 200
+
+ property alias text: edit.text
+ property alias wrapMode: edit.wrapMode
+ highlightOnFocus: true
+
+ TextEdit {
+ id: edit
+ text: loremIpsum + loremIpsum;
+ wrapMode: TextEdit.WordWrap;
+ width: area.contentWidth
+ selectByMouse:true
+
+ // keep textcursor within scrollarea
+ onCursorRectangleChanged:
+ if (cursorRectangle.y >= area.contentY + area.height - 1.5*cursorRectangle.height)
+ area.contentY = cursorRectangle.y - area.height + 1.5*cursorRectangle.height
+ else if (cursorRectangle.y < area.contentY)
+ area.contentY = cursorRectangle.y
+
+ }
+}
diff --git a/components/ToolBar.qml b/components/ToolBar.qml
new file mode 100644
index 00000000..ce61382e
--- /dev/null
+++ b/components/ToolBar.qml
@@ -0,0 +1,12 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+QStyleBackground {
+ id:styleitem
+ width:200
+ height:60
+
+ style: QStyleItem{elementType:"toolbar"}
+}
+
diff --git a/components/ToolButton.qml b/components/ToolButton.qml
new file mode 100644
index 00000000..98b2dfeb
--- /dev/null
+++ b/components/ToolButton.qml
@@ -0,0 +1,18 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Button {
+ id:button
+ minimumWidth:30
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType: "toolbutton"
+ on: pressed | checked
+ sunken: pressed
+ raised: containsMouse
+ hover: containsMouse
+ }
+ }
+}
diff --git a/components/custom/BasicButton.qml b/components/custom/BasicButton.qml
new file mode 100644
index 00000000..1116f0b0
--- /dev/null
+++ b/components/custom/BasicButton.qml
@@ -0,0 +1,44 @@
+import QtQuick 1.1
+import "./behaviors" // ButtonBehavior
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: button
+
+ signal clicked
+ property alias pressed: behavior.pressed
+ property alias containsMouse: behavior.containsMouse
+ property alias checkable: behavior.checkable // button toggles between checked and !checked
+ property alias checked: behavior.checked
+
+ property Component background: defaultStyle.background
+
+ property color backgroundColor: syspal.button
+ property color textColor: syspal.text;
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ // implementation
+
+ property string __position: "only"
+ implicitWidth: Math.max(minimumWidth, backgroundLoader.item.width)
+ implicitHeight: Math.max(minimumHeight, backgroundLoader.item.height)
+
+ Loader {
+ id: backgroundLoader
+ anchors.fill: parent
+ sourceComponent: background
+ property alias styledItem: button
+ property alias position: button.__position
+ }
+
+ ButtonBehavior {
+ id: behavior
+ anchors.fill: parent
+ onClicked: button.clicked()
+ }
+
+ DefaultStyles.BasicButtonStyle { id: defaultStyle }
+ SystemPalette { id: syspal }
+}
diff --git a/components/custom/BusyIndicator.qml b/components/custom/BusyIndicator.qml
new file mode 100644
index 00000000..00b12ed3
--- /dev/null
+++ b/components/custom/BusyIndicator.qml
@@ -0,0 +1,27 @@
+import QtQuick 1.0
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: busyIndicator
+
+ // Common API:
+ property bool running: true
+
+ width: backgroundComponent.item.width;
+ height: backgroundComponent.item.height;
+
+ property Component background: defaultStyle.background
+
+ Loader {
+ id: backgroundComponent
+ property bool running: busyIndicator.opacity > 0 &&
+ busyIndicator.visible &&
+ busyIndicator.running
+// onRunningChanged: print("Running: " + running)
+ anchors.fill: parent
+ sourceComponent: background
+
+ }
+
+ DefaultStyles.BusyIndicatorStyle { id: defaultStyle }
+}
diff --git a/components/custom/Button.qml b/components/custom/Button.qml
new file mode 100644
index 00000000..1bcd8335
--- /dev/null
+++ b/components/custom/Button.qml
@@ -0,0 +1,39 @@
+import QtQuick 1.1
+import "./styles/default" as DefaultStyles
+
+BasicButton {
+ id: button
+
+ property string text
+ property url iconSource
+
+ property Component label: defaultStyle.label
+
+ property int leftMargin: defaultStyle.leftMargin
+ property int topMargin: defaultStyle.topMargin
+ property int rightMargin: defaultStyle.rightMargin
+ property int bottomMargin: defaultStyle.bottomMargin
+
+ // implementation
+
+ implicitWidth: Math.max(minimumWidth, labelLoader.item.implicitWidth + leftMargin + rightMargin)
+ implicitHeight: Math.max(minimumHeight, labelLoader.item.implicitHeight + topMargin + bottomMargin)
+
+ minimumWidth: defaultStyle.minimumWidth
+ minimumHeight: defaultStyle.minimumHeight
+
+ background: defaultStyle.background
+
+ Loader {
+ id: labelLoader
+ anchors.fill: parent
+ anchors.leftMargin: leftMargin
+ anchors.rightMargin: rightMargin
+ anchors.topMargin: topMargin
+ anchors.bottomMargin: bottomMargin
+ property alias styledItem: button
+ sourceComponent: label
+ }
+
+ DefaultStyles.ButtonStyle { id: defaultStyle }
+}
diff --git a/components/custom/ButtonBlock.qml b/components/custom/ButtonBlock.qml
new file mode 100644
index 00000000..999d3dd0
--- /dev/null
+++ b/components/custom/ButtonBlock.qml
@@ -0,0 +1,216 @@
+import QtQuick 1.0
+import "./behaviors" // ButtonBehavior
+import "./visuals" // AdjoiningVisual
+import "./styles/default" as DefaultStyles
+
+// KNOWN ISSUES
+// 1) When switching between horizontal and vertical orientation after block has been created, the Grid's move
+// transition is called *before* the grid item's have actually moved, resulting in incorrect "adjoins" states
+// 2) Can't make items in vertical groups all the same width without access to their implicitWidth, see QTBUG-14957
+// 3) Should be generalized into JoinedGroup and ButtonBlock made a specialization.
+// 4) ExclusiveSelection support missing
+
+// NOTES
+// 1) The ButtonBlock implementation has no ultimate dependency on AdjoiningVisual, and can therefor be made to work
+// with any Component for the item instances. The use of AdjoiningVisual is only for simplifying the implementation
+// and styling of the items in the block. The property defining how an item in the block should be joinged with its
+// neighbours is "adjoins" which the ButtonBlock "attaches" to the items in the block (i.e. defines in their
+// look-up scope) which means the "button" instances does not need to define this property, only read it to draw
+// their border appropriately. This "adjoins" property is a *completely* separate concept from the AdjoiningVisual.
+// I.e. the coupling between the ButtonGroup and the "button" elements making up the group is the weakest possible.
+
+
+Item {
+ id: buttonBlock
+
+ property alias model: repeater.model
+ property variant bindings: {"text":"text", "iconSource":"iconSource", "enabled":"enabled", "opacity":"opacity"}
+
+ property Component buttonBackground: defaultStyle.background
+ property Component buttonLabel: defaultStyle.label
+
+ property color backgroundColor: syspal.button
+ property color textColor: syspal.text;
+
+ property int orientation: Qt.Horizontal
+ signal clicked(int index)
+
+ property int leftMargin: defaultStyle.leftMargin
+ property int topMargin: defaultStyle.topMargin
+ property int rightMargin: defaultStyle.rightMargin
+ property int bottomMargin: defaultStyle.bottomMargin
+
+ width: grid.width
+ height: grid.height
+
+ Grid {
+ id: grid
+ columns: orientation == Qt.Vertical ? 1 : model.count
+ anchors.centerIn: parent
+ property int widestItemWidth: 0
+ property int talestItemHeight: 0
+
+ move: Transition { //mm seems "move" transition is not always called after items has been moved
+ ScriptAction { script: {
+ if(orientation == Qt.Horizontal) {
+ grid.leftmostVisibleIndex = grid.__leftmostVisibleIndex();
+ grid.rightmostVisibleIndex = grid.__rightmostVisibleIndex();
+ } else {
+ grid.topmostVisibleIndex = grid.__topmostVisibleIndex();
+ grid.bottommostVisibleIndex = grid.__bottommostVisibleIndex();
+ }
+ }
+ }
+ }
+
+ property int leftmostVisibleIndex
+ function __leftmostVisibleIndex() {
+ var leftmostVisibleIndex = 0;
+ var leftmostItemX = 10000000;
+ for(var i = 0; i < children.length; i++) {
+ var child = children[i];
+ if(child.x < leftmostItemX && child.opacity > 0) {
+ leftmostItemX = child.x;
+ leftmostVisibleIndex = i;
+ }
+ }
+ return leftmostVisibleIndex;
+ }
+
+ property int rightmostVisibleIndex
+ function __rightmostVisibleIndex() {
+ var rightmostVisibleIndex = 0;
+ var rightmostItemX = 0;
+ for(var i = 0; i < children.length; i++) {
+ var child = children[i];
+//mm print("rightmost child? at: " + child.x + "," + child.y)
+ if(child.x > rightmostItemX && child.opacity > 0) {
+ rightmostItemX = child.x;
+ rightmostVisibleIndex = i;
+ }
+ }
+ return rightmostVisibleIndex;
+ }
+
+ property int topmostVisibleIndex
+ function __topmostVisibleIndex() {
+ var topmostVisibleIndex = 0;
+ var topmostItemY = 10000000;
+ for(var i = 0; i < children.length; i++) {
+ var child = children[i];
+ if(child.y < topmostItemY && child.opacity > 0) {
+ topmostItemY = child.y;
+ topmostVisibleIndex = i;
+ }
+ }
+ return topmostVisibleIndex;
+ }
+
+ property int bottommostVisibleIndex
+ function __bottommostVisibleIndex() {
+ var bottommostVisibleIndex = 0;
+ var bottommostItemY = 0;
+ for(var i = 0; i < children.length; i++) {
+ var child = children[i];
+//mm print("bottommost child? at: " + child.x + "," + child.y)
+ if(child.y > bottommostItemY && child.opacity > 0) {
+ bottommostItemY = child.y;
+ bottommostVisibleIndex = i;
+ }
+ }
+ return bottommostVisibleIndex;
+ }
+
+ Repeater {
+ id: repeater
+ delegate: AdjoiningVisual {
+ id: blockButton
+ styledItem: blockButton
+ styling: buttonBackground
+
+ property alias pressed: behavior.pressed
+ property alias containsMouse: behavior.containsMouse
+ property alias checkable: behavior.checkable // button toggles between checked and !checked
+ property alias checked: behavior.checked
+
+ property string text
+ property url iconSource
+ property color textColor: buttonBlock.textColor
+ property color backgroundColor: buttonBlock.backgroundColor
+
+ Component.onCompleted: {
+ // Create the Binding objects defined by the ButtonBlock's "bindings" map property to allow
+ // the properties of the buttons to be bound to properties in the model with different names
+
+ if (bindings == undefined) // jb : bindings is undefined on Mac
+ return;
+ var keys = Object.keys(buttonBlock.bindings);
+ for(var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ var bindingComponent =
+ 'import QtQuick 1.0;' +
+ 'Binding {' +
+ ' target: blockButton;' +
+ ' property: "' + key + '";' +
+ ' value: buttonBlock.model.get(' + index + ').' + bindings[key] + ';' +
+ '}';
+ Qt.createQmlObject(bindingComponent, blockButton); //mm do we ever need to explicitly delete these?
+ }
+
+ // Find the widest/talest item to make all buttons the same width/height
+ if(buttonBlock.orientation == Qt.Vertical) //mm Can't make this work without QTBUG-14957
+ grid.widestItemWidth = Math.max(grid.widestItemWidth, width);
+ else
+ grid.talestItemHeight = Math.max(grid.talestItemHeight, height);
+ }
+
+ ButtonBehavior {
+ id: behavior
+ anchors.fill: parent
+ onClicked: buttonBlock.clicked(index)
+ }
+
+ property int adjoins
+ adjoins: { //mm see QTBUG-14987
+ var adjoins;
+ if(orientation == Qt.Horizontal) {
+ adjoins = 0x1|0x2; // left and right
+ if(index == grid.leftmostVisibleIndex) adjoins &= ~0x1; // not left
+ if(index == grid.rightmostVisibleIndex) adjoins &= ~0x2; // not right
+ } else {
+ adjoins = 0x4|0x8; // top and bottom
+ if(index == grid.topmostVisibleIndex) adjoins &= ~0x4; // not top
+ if(index == grid.bottommostVisibleIndex) adjoins &= ~0x8; // not bottom
+ }
+ return adjoins;
+ }
+
+
+ // width: orientation == Qt.Vertical ? grid.widestItemWidth : item.width
+ // height: orientation == Qt.Vertical ? item.height : grid.talestItemHeight
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ width: Math.max(minimumWidth,
+ labelComponent.item.width + leftMargin + rightMargin)
+ height: Math.max(minimumHeight,
+ labelComponent.item.height + topMargin + bottomMargin)
+
+ Loader {
+ id: labelComponent
+ property variant styledItem: blockButton
+ anchors.fill: parent
+ anchors.leftMargin: leftMargin
+ anchors.rightMargin: rightMargin
+ anchors.topMargin: topMargin
+ anchors.bottomMargin: bottomMargin
+ sourceComponent: buttonLabel
+ }
+
+ }
+ }
+ }
+
+ SystemPalette { id: syspal; colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled }
+ DefaultStyles.ButtonBlockStyle { id: defaultStyle }
+}
diff --git a/components/custom/ButtonColumn.qml b/components/custom/ButtonColumn.qml
new file mode 100644
index 00000000..8d63a855
--- /dev/null
+++ b/components/custom/ButtonColumn.qml
@@ -0,0 +1,44 @@
+import Qt 4.7
+import "ButtonGroup.js" as Behavior
+
+/*
+ Class: ButtonColumn
+ A ButtonColumn allows you to group Buttons in a column. It provides a selection-behavior as well.
+
+ Note: This component don't support the enabled property.
+ If you need to disable it you should disable all the buttons inside it.
+
+ <code>
+ ButtonColumn {
+ Button { text: "Top" }
+ Button { text: "Bottom" }
+ }
+ </code>
+*/
+Column {
+ id: root
+
+ /*
+ * Property: exclusive
+ * [bool=true] Specifies the grouping behavior. If enabled, the checked property on buttons contained
+ * in the group will be exclusive.
+ *
+ * Note that a button in an exclusive group will allways be checkable
+ */
+ property bool exclusive: true
+
+ /*
+ * Property: checkedButton
+ * [string] Contains the last checked Button.
+ */
+ property Item checkedButton;
+
+ Component.onCompleted: {
+ Behavior.create(root, {direction: Qt.Vertical});
+ }
+
+ Component.onDestruction: {
+ Behavior.destroy();
+ }
+
+}
diff --git a/components/custom/ButtonGroup.js b/components/custom/ButtonGroup.js
new file mode 100644
index 00000000..f2d00002
--- /dev/null
+++ b/components/custom/ButtonGroup.js
@@ -0,0 +1,127 @@
+var self;
+var clickHandlers = [];
+var visibleButtons = [];
+var nonVisibleButtons = [];
+var direction;
+var exclusive;
+
+function create(that, options) {
+ self = that;
+ direction = options.direction || Qt.Horizontal;
+ exclusive = self.exclusive|| options.exclusive;
+ self.childrenChanged.connect(rebuild);
+// self.widthChanged.connect(resizeChildren);
+ build();
+}
+
+function isButton(item) {
+ if (item && item["__position"] !== undefined)
+ return true;
+ return false;
+}
+
+function hasChecked(item) {
+ if (item && item["checked"] !== undefined)
+ return true;
+ return false;
+}
+
+function destroy() {
+ self.childrenChanged.disconnect(rebuild);
+// self.widthChanged.disconnect(resizeChildren);
+ cleanup();
+}
+
+function build() {
+ visibleButtons = [];
+ nonVisibleButtons = [];
+
+ for (var i = 0, item; (item = self.children[i]); i++) {
+ if (!hasChecked(item))
+ continue;
+
+ item.visibleChanged.connect(rebuild); // Not optimal, but hardly a bottleneck in your app
+ if (!item.visible) {
+ nonVisibleButtons.push(item);
+ continue;
+ }
+ visibleButtons.push(item);
+
+ if (exclusive && hasChecked(item)) {
+ if (item["checkable"]!==undefined) {
+ item.checkable = true;
+ }
+ clickHandlers[i] = checkExclusive(item);
+ item.clicked.connect(clickHandlers[i]);
+ }
+ }
+
+ if (self.checkedButton && !self.checkedButton.visible)
+ self.checkedButton = undefined;
+
+ var nrButtons = visibleButtons.length;
+ if (nrButtons == 0)
+ return;
+
+ if (nrButtons == 1) {
+ finishButton(visibleButtons[0], "only");
+ } else {
+ finishButton(visibleButtons[0], direction == Qt.Horizontal ? "leftmost" : "top");
+ for (var i = 1; i < nrButtons - 1; i++)
+ finishButton(visibleButtons[i], direction == Qt.Horizontal ? "h_middle": "v_middle");
+ finishButton(visibleButtons[nrButtons - 1], direction == Qt.Horizontal ? "rightmost" : "bottom");
+ }
+}
+
+function finishButton(button, position) {
+ if (isButton(button)) {
+ button.__position = position;
+ if (direction == Qt.Vertical) {
+ button.anchors.left = self.left
+ button.anchors.right = self.right
+ }
+ }
+}
+
+function cleanup() {
+ visibleButtons.forEach(function(item, i) {
+ if (clickHandlers[i])
+ item.clicked.disconnect(clickHandlers[i]);
+ item.visibleChanged.disconnect(rebuild);
+ });
+ clickHandlers = [];
+
+ nonVisibleButtons.forEach(function(item, i) {
+ item.visibleChanged.disconnect(rebuild);
+ });
+}
+
+function rebuild() {
+ cleanup();
+ build();
+}
+
+function resizeChildren() {
+ if (direction != Qt.Horizontal)
+ return;
+
+ var extraPixels = self.width % visibleButtons;
+ var buttonSize = (self.width - extraPixels) / visibleButtons;
+ visibleButtons.forEach(function(item, i) {
+ if (!item || !item.visible)
+ return;
+ item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
+ if (extraPixels > 0)
+ extraPixels--;
+ });
+}
+
+function checkExclusive(item) {
+ var button = item;
+ return function() {
+ for (var i = 0, ref; (ref = visibleButtons[i]); i++) {
+ ref.checked = button === ref;
+ }
+ self.checkedButton = button;
+ }
+}
diff --git a/components/custom/ButtonRow.qml b/components/custom/ButtonRow.qml
new file mode 100644
index 00000000..7c2d3ea7
--- /dev/null
+++ b/components/custom/ButtonRow.qml
@@ -0,0 +1,43 @@
+import Qt 4.7
+import "ButtonGroup.js" as Behavior
+
+/*
+ Class: ButtonRow
+ A ButtonRow allows you to group Buttons in a row. It provides a selection-behavior as well.
+
+ Note: This component don't support the enabled property.
+ If you need to disable it you should disable all the buttons inside it.
+
+ <code>
+ ButtonRow {
+ Button { text: "Left" }
+ Button { text: "Right" }
+ }
+ </code>
+*/
+Row {
+ id: root
+
+ /*
+ * Property: exclusive
+ * [bool=true] Specifies the grouping behavior. If enabled, the checked property on buttons contained
+ * in the group will be exclusive.
+ *
+ * Note that a button in an exclusive group will allways be checkable
+ */
+ property bool exclusive: true
+
+ /*
+ * Property: checkedButton
+ * [string] Contains the last checked Button.
+ */
+ property Item checkedButton;
+
+ Component.onCompleted: {
+ Behavior.create(root, {direction: Qt.Horizontal});
+ }
+
+ Component.onDestruction: {
+ Behavior.destroy();
+ }
+}
diff --git a/components/custom/CheckBox.qml b/components/custom/CheckBox.qml
new file mode 100644
index 00000000..e8b86556
--- /dev/null
+++ b/components/custom/CheckBox.qml
@@ -0,0 +1,49 @@
+import QtQuick 1.1
+import "./behaviors"
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: checkBox
+
+ signal clicked
+ property alias pressed: behavior.pressed
+ property alias checked: behavior.checked
+ property alias containsMouse: behavior.containsMouse
+
+ property Component background: defaultStyle.background
+ property Component checkmark: defaultStyle.checkmark
+
+ property color backgroundColor: syspal.base
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ // implementation
+
+ implicitWidth: minimumWidth
+ implicitHeight: minimumHeight
+
+ Loader {
+ id: backgroundLoader
+ anchors.fill: parent
+ property alias styledItem: checkBox
+ sourceComponent: background
+ }
+
+ Loader {
+ id: checkmarkLoader
+ anchors.centerIn: parent
+ property alias styledItem: checkBox
+ sourceComponent: checkmark
+ }
+
+ ButtonBehavior {
+ id: behavior
+ anchors.fill: parent
+ checkable: true
+ onClicked: checkBox.clicked()
+ }
+
+ DefaultStyles.CheckBoxStyle { id: defaultStyle }
+ SystemPalette { id: syspal }
+}
diff --git a/components/custom/ChoiceList.qml b/components/custom/ChoiceList.qml
new file mode 100644
index 00000000..8c5ca81b
--- /dev/null
+++ b/components/custom/ChoiceList.qml
@@ -0,0 +1,85 @@
+import QtQuick 1.0
+import "./styles/default" as DefaultStyles
+import "./private" as Private // for ChoiceListPopup
+
+// KNOWN ISSUES
+// 1) Popout list does not have a scrollbar/scroll indicator or similar
+// 2) The ChoiceListPopup should ff dynamically loaded, to support radically different implementations
+// 3) Mouse wheel scroll events not handled by the popout ListView (see QTBUG-7369)
+// 4) Support for configurable bindings between model's and ChoiceList's properties similar to ButtonBlock's is missing
+
+Item {
+ id: choiceList
+
+ property alias model: popup.model
+ property int currentIndex: popup.currentIndex
+
+ property alias containsMouse: mouseArea.containsMouse //mm needed?
+ property bool pressed: false //mm needed?
+
+ property color textColor: syspal.text
+ property color backgroundColor: syspal.button
+
+ property Component background: defaultStyle.background
+ property Component label: defaultStyle.label
+ property Component listItem: defaultStyle.listItem
+ property Component popupFrame: defaultStyle.popupFrame
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ property int leftMargin: defaultStyle.leftMargin
+ property int topMargin: defaultStyle.topMargin
+ property int rightMargin: defaultStyle.rightMargin
+ property int bottomMargin: defaultStyle.bottomMargin
+
+ property int labelWidth: labelComponent.item.width
+ property int labelHeight: labelComponent.item.height
+
+ width: Math.max(minimumWidth,
+ labelComponent.item.width + leftMargin + rightMargin)
+ height: Math.max(minimumHeight,
+ labelComponent.item.height + topMargin + bottomMargin)
+
+ // Implementation
+
+ SystemPalette { id: syspal }
+ Loader {
+ property alias styledItem: choiceList
+ sourceComponent: background
+ anchors.fill: parent
+ }
+
+ Loader {
+ id: labelComponent
+ property alias model: popup.model
+ anchors.fill: parent
+ anchors.leftMargin: leftMargin
+ anchors.rightMargin: rightMargin
+ anchors.topMargin: topMargin
+ anchors.bottomMargin: bottomMargin
+ sourceComponent: label
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ drag.target: Item {} // disable dragging in case ChoiceList is on a Flickable
+ onPressed: {
+ choiceList.pressed = true;
+ popup.togglePopup();
+
+ }
+ onReleased: choiceList.pressed = false
+ onCanceled: choiceList.pressed = false // mouse stolen e.g. by Flickable
+ }
+
+ Private.ChoiceListPopup {
+ id: popup
+ listItem: choiceList.listItem
+ popupFrame: choiceList.popupFrame
+ }
+
+ DefaultStyles.ChoiceListStyle { id: defaultStyle }
+}
diff --git a/components/custom/ProgressBar.qml b/components/custom/ProgressBar.qml
new file mode 100644
index 00000000..fadbbc5e
--- /dev/null
+++ b/components/custom/ProgressBar.qml
@@ -0,0 +1,80 @@
+import QtQuick 1.0
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: progressBar
+ SystemPalette{id:syspal}
+
+ property real value: 0
+ property real minimumValue: 0
+ property real maximumValue: 1
+ property bool indeterminate: false
+
+ property color backgroundColor: syspal.base
+ property color progressColor: syspal.highlight
+
+ property int leftMargin: defaultStyle.leftMargin
+ property int topMargin: defaultStyle.topMargin
+ property int rightMargin: defaultStyle.rightMargin
+ property int bottomMargin: defaultStyle.bottomMargin
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ width: minimumWidth
+ height: minimumHeight
+
+ property Component background: defaultStyle.background
+ property Component progress: defaultStyle.progress
+ property Component indeterminateProgress: defaultStyle.indeterminateProgress
+
+ Loader {
+ id: groove
+ property alias indeterminate:progressBar.indeterminate
+ property alias value:progressBar.value
+ property alias maximumValue:progressBar.maximumValue
+ property alias minimumValue:progressBar.minimumValue
+
+ sourceComponent: background
+ anchors.fill: parent
+ }
+
+ Item {
+ anchors.fill: parent
+ anchors.leftMargin: leftMargin
+ anchors.rightMargin: rightMargin
+ anchors.topMargin: topMargin
+ anchors.bottomMargin: bottomMargin
+
+ Loader {
+ id: progressComponent
+ property alias styledItem: progressBar
+ property alias indeterminate:progressBar.indeterminate
+ property alias value:progressBar.value
+ property alias maximumValue:progressBar.maximumValue
+ property alias minimumValue:progressBar.minimumValue
+ property real complete: (value-minimumValue)/(maximumValue-minimumValue)
+
+ opacity: !indeterminate && value > 0 ? 1 : 0
+ width: Math.round((progressBar.width-leftMargin-rightMargin)*(complete))
+ height: progressBar.height-topMargin-bottomMargin
+ anchors.left:parent.left
+ sourceComponent: progressBar.progress
+ }
+
+ Loader {
+ id: indeterminateComponent
+ property alias styledItem: progressBar
+ property alias indeterminate:progressBar.indeterminate
+ property alias value:progressBar.value
+ property alias maximumValue:progressBar.maximumValue
+ property alias minimumValue:progressBar.minimumValue
+
+ opacity: indeterminate ? 1 : 0
+ anchors.fill: parent
+ sourceComponent: indeterminateProgress
+ }
+ }
+
+ DefaultStyles.ProgressBarStyle { id: defaultStyle }
+}
diff --git a/components/custom/RadioButton.qml b/components/custom/RadioButton.qml
new file mode 100644
index 00000000..f89f2773
--- /dev/null
+++ b/components/custom/RadioButton.qml
@@ -0,0 +1,13 @@
+import QtQuick 1.1
+import "./styles/default" as DefaultStyles
+
+CheckBox {
+ id: radioButton
+
+ // implementation
+
+ checkmark: defaultStyle.checkmark
+ background: defaultStyle.background
+
+ DefaultStyles.RadioButtonStyle { id: defaultStyle}
+}
diff --git a/components/custom/ScrollDecorator.qml b/components/custom/ScrollDecorator.qml
new file mode 100644
index 00000000..e61a16d2
--- /dev/null
+++ b/components/custom/ScrollDecorator.qml
@@ -0,0 +1,20 @@
+import QtQuick 1.0
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: scrollDecorator
+
+ property Flickable flickableItem
+
+ anchors.fill: parent
+
+ ScrollIndicator {
+ horizontal: true
+ scrollItem: scrollDecorator.flickableItem
+ }
+
+ ScrollIndicator {
+ horizontal: false
+ scrollItem: scrollDecorator.flickableItem
+ }
+}
diff --git a/components/custom/ScrollIndicator.qml b/components/custom/ScrollIndicator.qml
new file mode 100644
index 00000000..cba1dba8
--- /dev/null
+++ b/components/custom/ScrollIndicator.qml
@@ -0,0 +1,56 @@
+import QtQuick 1.0
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: scrollIndicator
+
+ property Flickable scrollItem
+ property bool horizontal: false
+
+ property Component content: defaultStyle.content
+
+ //private
+ anchors.left: horizontal ? parent.left : undefined
+ anchors.right: parent.right
+ anchors.top: horizontal ? undefined : parent.top
+ anchors.bottom: parent.bottom
+ width: horizontal ? parent.width : defaultStyle.minimumWidth
+ height: horizontal ? defaultStyle.minimumWidth : parent.height
+
+ opacity: (horizontal ? scrollItem.movingHorizontally : scrollItem.movingVertically) ? 1 : 0
+ Behavior on opacity { NumberAnimation { duration: 100 } }
+
+ Item {
+ id: ratationContainer
+
+ anchors.centerIn: parent
+ rotation: horizontal ? -90 : 0
+ width: horizontal ? scrollIndicator.height : scrollIndicator.width // rotate width and heigh back
+ height: horizontal ? scrollIndicator.width : scrollIndicator.height
+
+ property variant visibleArea: scrollItem.visibleArea
+ property real scrollItemSize: horizontal ? scrollItem.width : scrollItem.height
+ property real scrollItemVisibleAreaPos: horizontal ? visibleArea.xPosition : visibleArea.yPosition
+ property real scrollItemVisibleAreaScrollRatio: horizontal ? visibleArea.widthRatio : visibleArea.heightRatio
+ property real scrollItemContentPos: horizontal ? scrollItem.contentX : scrollItem.contentY
+ property real scrollItemContentSize: horizontal ? scrollItem.contentWidth : scrollItem.contentHeight
+
+ property real offset: scrollItemVisibleAreaPos * scrollItemSize
+ property real length: scrollItemVisibleAreaScrollRatio * scrollItemSize
+ property real startOvershoot: Math.max(-scrollItemContentPos, 0)
+ property real endOvershoot: Math.max(scrollItemContentPos-(scrollItemContentSize-scrollItemSize), 0)
+ property real start: Math.max(offset + endOvershoot, 0)
+ property real end: Math.min(offset+length-startOvershoot, scrollItemSize)
+
+ Loader {
+ x: 0
+ y: parent.endOvershoot > 0 ? Math.min(parent.start, parent.scrollItemSize-width) : parent.start
+ width: 12
+ height: Math.max(parent.end-parent.start, width)
+
+ sourceComponent: content
+ }
+ }
+
+ DefaultStyles.ScrollIndicatorStyle { id: defaultStyle }
+}
diff --git a/components/custom/Slider.qml b/components/custom/Slider.qml
new file mode 100644
index 00000000..789167c6
--- /dev/null
+++ b/components/custom/Slider.qml
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Components project on Qt Labs.
+**
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions contained
+** in the Technology Preview License Agreement accompanying this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import Qt.labs.components 1.0
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: slider
+
+ // COMMON API
+ property int orientation: Qt.Horizontal
+ property alias minimumValue: range.minimumValue
+ property alias maximumValue: range.maximumValue
+ property alias inverted: range.inverted
+ property bool updateValueWhileDragging: true
+ property alias pressed: mouseArea.pressed
+ property alias stepSize: range.stepSize
+
+ // NOTE: this property is in/out, the user can set it, create bindings to it, and
+ // at the same time the slider wants to update. There's no way in QML to do this kind
+ // of updates AND allow the user bind it (without a Binding object). That's the
+ // reason this is an alias to a C++ property in range model.
+ property alias value: range.value
+
+ // CONVENIENCE TO BE USED BY STYLES
+ SystemPalette {
+ id: palette
+ }
+ property color progressColor: palette.highlight
+ property color backgroundColor: palette.window
+
+ property int leftMargin: defaultStyle.leftMargin
+ property int rightMargin: defaultStyle.rightMargin
+
+ // EXTENSIONS
+ // Indicate that we want animations in the Slider, people customizing should
+ // look at it to decide whether or not active animations.
+ property bool animated: true
+
+ // Value indicator displays the current value near the slider
+ property bool valueIndicatorVisible: true
+ property int valueIndicatorMargin: 10
+ property string valueIndicatorPosition: _isVertical ? "Left" : "Top"
+
+ // Reimplement this function to control how the value is shown in the
+ // indicator.
+ function formatValue(v) {
+ return Math.round(v);
+ }
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ // Hooks for customizing the pieces of the slider
+ property Component groove: defaultStyle.groove
+ property Component handle: defaultStyle.handle
+ property Component valueIndicator: defaultStyle.valueIndicator
+
+ // PRIVATE/CONVENIENCE
+ property bool _isVertical: orientation == Qt.Vertical
+
+ width: _isVertical ? minimumHeight : minimumWidth
+ height: _isVertical ? minimumWidth : minimumHeight
+
+ DefaultStyles.SliderStyle { id: defaultStyle }
+
+ // This is a template slider, so every piece can be modified by passing a
+ // different Component. The main elements in the implementation are
+ //
+ // - the 'range' does the calculations to map position to/from value,
+ // it also serves as a data storage for both properties;
+ //
+ // - the 'fakeHandle' is what the mouse area drags on the screen, it feeds
+ // the 'range' position and also reads it when convenient;
+ //
+ // - the real 'handle' it is the visual representation of the handle, that
+ // just follows the 'fakeHandle' position.
+ //
+ // When the 'updateValueWhileDragging' is false and we are dragging, we stop
+ // feeding the range with position information, delaying until the next
+ // mouse release.
+ //
+ // Everything is encapsulated in a contents Item, so for the
+ // vertical slider, we just swap the height/width, make it
+ // horizontal, and then use rotation to make it vertical again.
+
+ Item {
+ id: contents
+
+ width: _isVertical ? slider.height : slider.width
+ height: _isVertical ? slider.width : slider.height
+ rotation: _isVertical ? -90 : 0
+
+ anchors.centerIn: slider
+
+ RangeModel {
+ id: range
+ minimumValue: 0
+ maximumValue: 100
+ value: 0
+ stepSize: 1.0
+ inverted: false
+
+ positionAtMinimum: leftMargin
+ positionAtMaximum: contents.width - rightMargin
+ }
+
+ Loader {
+ id: grooveLoader
+ anchors.fill: parent
+ sourceComponent: groove
+
+ property real handlePosition : handleLoader.x
+ function positionForValue(value) {
+ return range.positionForValue(value) - leftMargin;
+ }
+ }
+
+ Loader {
+ id: handleLoader
+ transform: Translate { x: - handleLoader.width / 2 }
+
+ anchors.verticalCenter: grooveLoader.verticalCenter
+
+ sourceComponent: handle
+
+ x: fakeHandle.x
+ Behavior on x {
+ id: behavior
+ enabled: !mouseArea.drag.active && slider.animated
+
+ PropertyAnimation {
+ duration: behavior.enabled ? 150 : 0
+ easing.type: Easing.OutSine
+ }
+ }
+ }
+
+ Item {
+ id: fakeHandle
+ width: handleLoader.width
+ height: handleLoader.height
+ transform: Translate { x: - handleLoader.width / 2 }
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.centerIn: parent
+ anchors.horizontalCenterOffset: (slider.leftMargin - slider.rightMargin) / 2
+
+ width: parent.width + handleLoader.width - slider.rightMargin - slider.leftMargin
+ height: parent.height
+
+ drag.target: fakeHandle
+ drag.axis: Drag.XAxis
+ drag.minimumX: range.positionAtMinimum
+ drag.maximumX: range.positionAtMaximum
+
+ onPressed: {
+ // Clamp the value
+ var newX = Math.max(mouse.x, drag.minimumX);
+ newX = Math.min(newX, drag.maximumX);
+
+ // Debounce the press: a press event inside the handler will not
+ // change its position, the user needs to drag it.
+ if (Math.abs(newX - fakeHandle.x) > handleLoader.width / 2)
+ range.position = newX;
+ }
+
+ onReleased: {
+ // If we don't update while dragging, this is the only
+ // moment that the range is updated.
+ if (!slider.updateValueWhileDragging)
+ range.position = fakeHandle.x;
+ }
+ }
+
+ Loader {
+ id: valueIndicatorLoader
+
+ transform: Translate { x: - handleLoader.width / 2 }
+ rotation: _isVertical ? 90 : 0
+ visible: valueIndicatorVisible
+
+ // Properties available for the delegate component. Note that the indicatorText
+ // shows the value for the position the handle is, which is not necessarily the
+ // available as the current slider.value, since updateValueWhileDragging can
+ // be set to 'false'.
+ property string indicatorText: slider.formatValue(range.valueForPosition(handleLoader.x))
+ property bool dragging: mouseArea.drag.active
+
+ sourceComponent: valueIndicator
+
+ state: {
+ if (!_isVertical)
+ return slider.valueIndicatorPosition;
+
+ if (valueIndicatorPosition == "Right")
+ return "Bottom";
+ if (valueIndicatorPosition == "Top")
+ return "Right";
+ if (valueIndicatorPosition == "Bottom")
+ return "Left";
+
+ return "Top";
+ }
+
+ anchors.margins: valueIndicatorMargin
+
+ states: [
+ State {
+ name: "Top"
+ AnchorChanges {
+ target: valueIndicatorLoader
+ anchors.bottom: handleLoader.top
+ anchors.horizontalCenter: handleLoader.horizontalCenter
+ }
+ },
+ State {
+ name: "Bottom"
+ AnchorChanges {
+ target: valueIndicatorLoader
+ anchors.top: handleLoader.bottom
+ anchors.horizontalCenter: handleLoader.horizontalCenter
+ }
+ },
+ State {
+ name: "Right"
+ AnchorChanges {
+ target: valueIndicatorLoader
+ anchors.left: handleLoader.right
+ anchors.verticalCenter: handleLoader.verticalCenter
+ }
+ },
+ State {
+ name: "Left"
+ AnchorChanges {
+ target: valueIndicatorLoader
+ anchors.right: handleLoader.left
+ anchors.verticalCenter: handleLoader.verticalCenter
+ }
+ }
+ ]
+ }
+ }
+
+ // Range position normally follow fakeHandle, except when
+ // 'updateValueWhileDragging' is false. In this case it will only follow
+ // if the user is not pressing the handle.
+ Binding {
+ when: updateValueWhileDragging || !mouseArea.pressed
+ target: range
+ property: "position"
+ value: fakeHandle.x
+ }
+
+ // During the drag, we simply ignore position set from the range, this
+ // means that setting a value while dragging will not "interrupt" the
+ // dragging activity.
+ Binding {
+ when: !mouseArea.drag.active
+ target: fakeHandle
+ property: "x"
+ value: range.position
+ }
+}
diff --git a/components/custom/SpinBox.qml b/components/custom/SpinBox.qml
new file mode 100644
index 00000000..1566a8e7
--- /dev/null
+++ b/components/custom/SpinBox.qml
@@ -0,0 +1,142 @@
+import QtQuick 1.0
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: spinbox
+ SystemPalette{id:syspal}
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ property int leftMargin: defaultStyle.leftMargin
+ property int topMargin: defaultStyle.topMargin
+ property int rightMargin: defaultStyle.rightMargin
+ property int bottomMargin: defaultStyle.bottomMargin
+
+ width: Math.max(minimumWidth,
+ input.width + leftMargin + rightMargin)
+
+ height: Math.max(minimumHeight,
+ input.height + topMargin + bottomMargin)
+
+ property real value: 0.0
+ property real maximumValue: 99
+ property real minimumValue: 0
+ property real singlestep: 1
+
+ property bool upEnabled: value != maximumValue;
+ property bool downEnabled: value != minimumValue;
+
+ property alias upPressed: mouseUp.pressed
+ property alias downPressed: mouseDown.pressed
+ property alias upHovered: mouseUp.containsMouse
+ property alias downHovered: mouseDown.containsMouse
+ property alias containsMouse: mouseArea.containsMouse
+ property alias activeFocus: input.activeFocus // Forward active focus
+
+ property color backgroundColor: syspal.base
+ property color textColor: syspal.text
+
+ property Component background: defaultStyle.background
+ property Component up: defaultStyle.up
+ property Component down: defaultStyle.down
+ DefaultStyles.SpinBoxStyle { id: defaultStyle }
+
+ function increment() {
+ value += singlestep
+ if (value > maximumValue)
+ value = maximumValue
+ input.text = value
+ }
+
+ function decrement() {
+ value -= singlestep
+ if (value < minimumValue)
+ value = minimumValue
+ input.text = value
+ }
+
+ function setValue(v) {
+ var newval = parseFloat(v)
+ if (newval > maximumValue)
+ newval = maximumValue
+ else if (value < minimumValue)
+ newval = minimumValue
+ value = newval
+ input.text = value
+ }
+
+ // background
+ Loader {
+ id: backgroundComponent
+ anchors.fill: parent
+ sourceComponent: background
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+
+ TextInput {
+ id: input
+ font.pixelSize: 14
+ anchors.margins: 5
+ anchors.leftMargin: leftMargin
+ anchors.topMargin: topMargin
+ anchors.rightMargin: rightMargin
+ anchors.bottomMargin: bottomMargin
+ anchors.fill: parent
+ selectByMouse: true
+ text: spinbox.value
+ validator: DoubleValidator { bottom: 11; top: 31 }
+ onTextChanged: { spinbox.setValue(text); }
+ color: textColor
+ opacity: parent.enabled ? 1 : 0.5
+ }
+
+ Loader {
+ id: upButton
+ property alias pressed : spinbox.upPressed
+ property alias hover : spinbox.upHovered
+ property alias enabled : spinbox.upEnabled
+ sourceComponent: up
+ MouseArea {
+ id: mouseUp
+ anchors.fill: upButton.item
+ onClicked: increment()
+
+ property bool autoincrement: false;
+ onReleased: autoincrement = false
+ Timer { running: mouseUp.pressed; interval: 350 ; onTriggered: mouseUp.autoincrement = true }
+ Timer { running: mouseUp.autoincrement; interval: 60 ; repeat: true ; onTriggered: increment() }
+ }
+ onLoaded: {
+ item.parent = spinbox
+ mouseUp.parent = item
+ }
+ }
+
+ Loader {
+ id: downButton
+ property alias pressed : spinbox.downPressed
+ property alias hover : spinbox.downHovered
+ property alias enabled : spinbox.downEnabled
+ sourceComponent: down
+ MouseArea {
+ id: mouseDown
+ anchors.fill: downButton.item
+ onClicked: decrement()
+
+ property bool autoincrement: false;
+ onReleased: autoincrement = false
+ Timer { running: mouseDown.pressed; interval: 350 ; onTriggered: mouseDown.autoincrement = true }
+ Timer { running: mouseDown.autoincrement; interval: 60 ; repeat: true ; onTriggered: decrement() }
+ }
+ onLoaded: {
+ item.parent = spinbox
+ mouseDown.parent = item
+ }
+ }
+}
diff --git a/components/custom/Switch.qml b/components/custom/Switch.qml
new file mode 100644
index 00000000..8bf18cfe
--- /dev/null
+++ b/components/custom/Switch.qml
@@ -0,0 +1,85 @@
+import QtQuick 1.1
+import "./styles/default" as DefaultStyles
+
+Item {
+ id: toggleSwitch // "switch" is a reserved word
+
+ signal clicked
+ property bool pressed: mouseArea.pressed
+ property bool checked: false
+ property alias containsMouse: mouseArea.containsMouse
+
+ property color switchColor: syspal.button
+ property color backgroundColor: syspal.alternateBase
+ property color positiveHighlightColor: syspal.highlight
+ property color negativeHighlightColor: "transparent"
+ property color textColor: syspal.text
+
+ property Component groove: defaultStyle.groove
+ property Component handle: defaultStyle.handle
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ // implementation
+
+ implicitWidth: Math.max(minimumWidth, grooveLoader.item.implicitWidth)
+ implicitHeight: Math.max(minimumHeight, grooveLoader.item.implicitHeight)
+
+ onCheckedChanged: snapHandleIntoPlace();
+
+ Loader {
+ id: grooveLoader
+ anchors.fill: parent
+ property alias styledItem: toggleSwitch
+ property real handleCenterX: handleLoader.item.x + (handleLoader.item.width/2)
+ sourceComponent: groove
+ }
+
+ Loader {
+ id: handleLoader
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ property alias styledItem: toggleSwitch
+ sourceComponent: handle
+
+ Component.onCompleted: item.x = checked ? mouseArea.drag.maximumX : mouseArea.drag.minimumX
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ drag.axis: Drag.XAxis
+ drag.minimumX: 0
+ drag.maximumX: toggleSwitch.width - handleLoader.item.width
+ drag.target: handleLoader.item
+
+ onPressed: toggleSwitch.pressed = true // needed when hover is enabled
+ onCanceled: { snapHandleIntoPlace(); toggleSwitch.pressed = false; } // mouse stolen e.g. by Flickable
+ onReleased: {
+ var wasChecked = checked;
+ if (drag.active) {
+ checked = (handleLoader.item.x > (drag.maximumX - drag.minimumX)/2)
+ } else if (toggleSwitch.pressed && enabled) { // No click if release outside area
+ checked = !checked;
+ }
+
+ snapHandleIntoPlace();
+
+ toggleSwitch.pressed = false
+ if(checked != wasChecked)
+ toggleSwitch.clicked();
+ }
+ }
+
+ onWidthChanged: snapHandleIntoPlace()
+ function snapHandleIntoPlace() {
+ if(handleLoader.item)
+ handleLoader.item.x = checked ? mouseArea.drag.maximumX : mouseArea.drag.minimumX;
+ }
+
+ DefaultStyles.SwitchStyle { id: defaultStyle }
+ SystemPalette { id: syspal }
+}
diff --git a/components/custom/TextArea.qml b/components/custom/TextArea.qml
new file mode 100644
index 00000000..92263fe6
--- /dev/null
+++ b/components/custom/TextArea.qml
@@ -0,0 +1,156 @@
+import QtQuick 1.0
+import "./styles/default" as DefaultStyles
+import "./behaviors" // TextEditMouseBehavior
+
+FocusScope {
+ id: textArea
+
+ property alias text: textEdit.text
+ property alias placeholderText: placeholderTextComponent.text
+ property alias font: textEdit.font
+ property bool passwordMode: false
+ property bool readOnly: textEdit.readOnly // read only
+ property int inputHint; // values tbd (alias to TextEdit.inputMethodHints?
+ property alias selectedText: textEdit.selectedText
+ property alias selectionEnd: textEdit.selectionEnd
+ property alias selectionStart: textEdit.selectionStart
+ property alias horizontalAlignment: textEdit.horizontalAlignment
+ property alias verticalAlignment: textEdit.verticalAlignment
+ property alias wrapMode: textEdit.wrapMode //mm Missing from spec
+ property alias textFormat: textEdit.textFormat
+ property alias cursorPosition: textEdit.cursorPosition
+
+ property color textColor: syspal.text
+ property color backgroundColor: syspal.base
+ property alias containsMouse: mouseEditBehavior.containsMouse
+
+ property Component background: defaultStyle.background
+ property Component hints: defaultStyle.hints
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ property int leftMargin: defaultStyle.leftMargin
+ property int topMargin: defaultStyle.topMargin
+ property int rightMargin: defaultStyle.rightMargin
+ property int bottomMargin: defaultStyle.bottomMargin
+
+ function copy() {
+ textEdit.copy()
+ }
+
+ function paste() {
+ textEdit.paste()
+ }
+
+ function cut() {
+ textEdit.cut()
+ }
+
+ function forceActiveFocus() {
+ textEdit.forceActiveFocus()
+ }
+
+ function select(start, end) {
+ textEdit.select(start, end)
+ }
+
+ function selectAll() {
+ textEdit.selectAll()
+ }
+
+ function selectWord() {
+ textEdit.selectWord()
+ }
+
+ function positionAt(x, y) {
+ var p = mapToItem(textEdit, x, y);
+ return textEdit.positionAt(p.x, p.y);
+ }
+
+ function positionToRectangle(pos) {
+ var p = mapToItem(textEdit, pos.x, pos.y);
+ return textEdit.positionToRectangle(p);
+ }
+
+ width: Math.max(minimumWidth,
+ Math.max(textEdit.width, placeholderTextComponent.width) + leftMargin + rightMargin)
+ height: Math.max(minimumHeight,
+ Math.max(textEdit.height, placeholderTextComponent.height) + topMargin + bottomMargin)
+
+
+ // Implementation
+
+ property alias activeFocus: textEdit.activeFocus // Forward active focus
+ property alias desktopBehavior: mouseEditBehavior.desktopBehavior
+ property alias _hints: hintsLoader.item
+ clip: true
+
+ SystemPalette { id: syspal }
+ Loader { id: hintsLoader; sourceComponent: hints }
+ Loader { sourceComponent: background; anchors.fill: parent }
+
+ Flickable { //mm is FocusScope, so TextArea's root doesn't need to be, no?
+ id: flickable
+ clip: true
+
+ anchors.fill: parent
+ anchors.leftMargin: leftMargin
+ anchors.topMargin: topMargin
+ anchors.rightMargin: rightMargin
+ anchors.bottomMargin: bottomMargin
+
+ function ensureVisible(r) {
+ if (contentX >= r.x)
+ contentX = r.x;
+ else if (contentX+width <= r.x+r.width)
+ contentX = r.x+r.width-width;
+ if (contentY >= r.y)
+ contentY = r.y;
+ else if (contentY+height <= r.y+r.height)
+ contentY = r.y+r.height-height;
+ }
+
+ TextEdit { // see QTBUG-14936
+ id: textEdit
+ font.pixelSize: _hints.fontPixelSize
+ font.bold: _hints.fontBold
+
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ color: enabled ? textColor: Qt.tint(textColor, "#80ffffff")
+ wrapMode: desktopBehavior ? TextEdit.NoWrap : TextEdit.WordWrap
+ onCursorRectangleChanged: flickable.ensureVisible(cursorRectangle)
+
+ onActiveFocusChanged: activeFocus ? openSoftwareInputPanel() : closeSoftwareInputPanel()
+ }
+ }
+
+ Text {
+ id: placeholderTextComponent
+ x: leftMargin; y: topMargin
+ font: textEdit.font
+ opacity: !textEdit.text.length && !textEdit.activeFocus ? 1 : 0
+ color: "gray"
+ clip: true
+ text: "Enter text"
+ Behavior on opacity { NumberAnimation { duration: 90 } }
+ }
+
+
+ TextEditMouseBehavior {
+ id: mouseEditBehavior
+ anchors.fill: parent
+ textEdit: textEdit
+ desktopBehavior: false
+ copyPasteButtons: ButtonBlock {
+ opacity: 0 // initially hidden
+ Behavior on opacity { NumberAnimation { duration: 100 } }
+ }
+ }
+
+ DefaultStyles.TextFieldStyle { id: defaultStyle }
+}
+
diff --git a/components/custom/TextField.qml b/components/custom/TextField.qml
new file mode 100644
index 00000000..2af29427
--- /dev/null
+++ b/components/custom/TextField.qml
@@ -0,0 +1,196 @@
+import QtQuick 1.0
+import "./styles/default" as DefaultStyles
+import "./behaviors" // TextEditMouseBehavior
+
+// KNOWN ISSUES
+// 1) TextField does not loose focus when !enabled if it is a FocusScope (see QTBUG-16161)
+
+FocusScope {
+ id: textField
+
+ property alias text: textInput.text
+ property alias font: textInput.font
+
+ property int inputHint // values tbd
+ property bool acceptableInput: textInput.acceptableInput // read only
+ property bool readOnly: textInput.readOnly // read only
+ property alias placeholderText: placeholderTextComponent.text
+ property bool passwordMode: false
+ property alias selectedText: textInput.selectedText
+ property alias selectionEnd: textInput.selectionEnd
+ property alias selectionStart: textInput.selectionStart
+ property alias validator: textInput.validator
+ property alias inputMask: textInput.inputMask
+ property alias horizontalalignment: textInput.horizontalAlignment
+ property alias echoMode: textInput.echoMode
+ property alias cursorPosition: textInput.cursorPosition
+ property alias inputMethodHints: textInput.inputMethodHints
+
+ property color textColor: syspal.text
+ property color backgroundColor: syspal.base
+ property alias containsMouse: mouseEditBehavior.containsMouse
+
+ property Component background: defaultStyle.background
+ property Component hints: defaultStyle.hints
+
+ property int minimumWidth: defaultStyle.minimumWidth
+ property int minimumHeight: defaultStyle.minimumHeight
+
+ property int leftMargin: defaultStyle.leftMargin
+ property int topMargin: defaultStyle.topMargin
+ property int rightMargin: defaultStyle.rightMargin
+ property int bottomMargin: defaultStyle.bottomMargin
+
+ function copy() {
+ textInput.copy()
+ }
+
+ function paste() {
+ textInput.paste()
+ }
+
+ function cut() {
+ textInput.cut()
+ }
+
+ function select(start, end) {
+ textInput.select(start, end)
+ }
+
+ function selectAll() {
+ textInput.selectAll()
+ }
+
+ function selectWord() {
+ textInput.selectWord()
+ }
+
+ function positionAt(x) {
+ var p = mapToItem(textInput, x, 0);
+ return textInput.positionAt(p.x);
+ }
+
+ function positionToRectangle(pos) {
+ var p = mapToItem(textInput, pos.x, pos.y);
+ return textInput.positionToRectangle(p);
+ }
+
+ width: Math.max(minimumWidth,
+ textInput.width + leftMargin + rightMargin)
+
+ height: Math.max(minimumHeight,
+ textInput.height + topMargin + bottomMargin)
+
+ // Forward focus property
+ property alias activeFocus: textInput.activeFocus
+
+ // Implementation
+
+ property alias desktopBehavior: mouseEditBehavior.desktopBehavior
+ property alias _hints: hintsLoader.item
+ clip: true
+
+ SystemPalette { id: syspal }
+ Loader { id: hintsLoader; sourceComponent: hints }
+ Loader { sourceComponent: background; anchors.fill:parent}
+
+ TextInput { // see QTBUG-14936
+ id: textInput
+ font.pixelSize: _hints.fontPixelSize
+ font.bold: _hints.fontBold
+
+ anchors.leftMargin: leftMargin
+ anchors.topMargin: topMargin
+ anchors.rightMargin: rightMargin
+ anchors.bottomMargin: bottomMargin
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+
+ opacity: desktopBehavior || activeFocus ? 1 : 0
+ color: enabled ? textColor : Qt.tint(textColor, "#80ffffff")
+ echoMode: passwordMode ? _hints.passwordEchoMode : TextInput.Normal
+
+ onActiveFocusChanged: {
+ if (!desktopBehavior)
+ state = (activeFocus ? "focused" : "")
+
+ if (activeFocus)
+ openSoftwareInputPanel()
+ else
+ closeSoftwareInputPanel()
+ }
+
+ states: [
+ State {
+ name: ""
+ PropertyChanges { target: textInput; cursorPosition: 0 }
+ },
+ State {
+ name: "focused"
+ PropertyChanges { target: textInput; cursorPosition: textInput.text.length }
+ }
+ ]
+
+ transitions: Transition {
+ to: "focused"
+ SequentialAnimation {
+ ScriptAction { script: textInput.cursorVisible = false; }
+ ScriptAction { script: textInput.cursorPosition = textInput.positionAt(textInput.width); }
+ NumberAnimation { target: textInput; property: "cursorPosition"; duration: 150 }
+ ScriptAction { script: textInput.cursorVisible = true; }
+ }
+ }
+ }
+
+ Text {
+ id: placeholderTextComponent
+ anchors.fill: textInput
+ font: textInput.font
+ opacity: !textInput.text.length && !textInput.activeFocus ? 1 : 0
+ color: "gray"
+ text: "Enter text"
+ Behavior on opacity { NumberAnimation { duration: 90 } }
+ }
+
+ Text {
+ id: unfocusedText
+ clip: true
+ anchors.fill: textInput
+ font: textInput.font
+ opacity: !desktopBehavior && !passwordMode && textInput.text.length && !textInput.activeFocus ? 1 : 0
+ color: textInput.color
+ elide: Text.ElideRight
+ text: textInput.text
+ }
+
+
+ TextEditMouseBehavior {
+ id: mouseEditBehavior
+ anchors.fill: parent
+ textInput: textInput
+ desktopBehavior: false
+ copyPasteButtons: ButtonBlock {
+ opacity: 0 // initially hidden
+ Behavior on opacity { NumberAnimation { duration: 100 } }
+ }
+ }
+
+ DefaultStyles.TextFieldStyle { id: defaultStyle }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/custom/behaviors/ButtonBehavior.qml b/components/custom/behaviors/ButtonBehavior.qml
new file mode 100644
index 00000000..391c870a
--- /dev/null
+++ b/components/custom/behaviors/ButtonBehavior.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+
+Item {
+ id: behavior
+
+ signal clicked
+ property bool pressed: false // Can't be alias of mouseArea.pressed because the latter is read-only
+ property alias containsMouse: mouseArea.containsMouse
+ property bool checkable: false
+ property bool checked: false
+ property bool triState: false
+
+ onCheckableChanged: { if(!checkable) checked = false }
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onPressed: behavior.pressed = true // needed when hover is enabled
+ onEntered: if(pressed && enabled) behavior.pressed = true
+ onExited: behavior.pressed = false
+ onCanceled: behavior.pressed = false // mouse stolen e.g. by Flickable
+ onReleased: {
+ if(behavior.pressed && behavior.enabled) { // No click if release outside area
+ behavior.pressed = false
+ if(behavior.checkable)
+ behavior.checked = !behavior.checked;
+ behavior.clicked()
+ }
+ }
+ }
+}
diff --git a/components/custom/behaviors/ModalPopupBehavior.qml b/components/custom/behaviors/ModalPopupBehavior.qml
new file mode 100644
index 00000000..108bf02a
--- /dev/null
+++ b/components/custom/behaviors/ModalPopupBehavior.qml
@@ -0,0 +1,90 @@
+import QtQuick 1.0
+
+// KNOWN ISSUES
+// none
+
+Item {
+ id: popupBehavior
+
+ property bool showing: false
+ property bool whenAlso: true // modifier to the "showing" property
+ property bool consumeCancelClick: true
+ property int delay: 0 // delay before popout becomes visible
+ property int deallocationDelay: 3000 // 3 seconds
+
+ property Component popupComponent
+
+ property alias popup: popupLoader.item // read-only
+ property alias window: popupBehavior.root // read-only
+
+ signal prepareToShow
+ signal prepareToHide
+ signal cancelledByClick
+
+ // implementation
+
+ anchors.fill: parent
+
+ onShowingChanged: notifyChange()
+ onWhenAlsoChanged: notifyChange()
+ function notifyChange() {
+ if(showing && whenAlso) {
+ if(popupLoader.sourceComponent == undefined) {
+ popupLoader.sourceComponent = popupComponent;
+ }
+ } else {
+ mouseArea.enabled = false; // disable before opacity is changed in case it has fading behavior
+ if(Qt.isQtObject(popupLoader.item)) {
+ popupBehavior.prepareToHide();
+ popupLoader.item.opacity = 0;
+ }
+ }
+ }
+
+ property Item root: findRoot()
+ function findRoot() {
+ var p = parent;
+ while(p.parent != undefined)
+ p = p.parent;
+
+ return p;
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ enabled: false // enabled only when popout is showing
+ onPressed: {
+ popupBehavior.showing = false;
+ mouse.accepted = consumeCancelClick;
+ cancelledByClick();
+ }
+ }
+
+ Loader {
+ id: popupLoader
+ }
+
+ Timer { // visibility timer
+ running: Qt.isQtObject(popupLoader.item) && showing && whenAlso
+ interval: delay
+ onTriggered: {
+ popupBehavior.prepareToShow();
+ mouseArea.enabled = true;
+ popup.opacity = 1;
+ }
+ }
+
+ Timer { // deallocation timer
+ running: Qt.isQtObject(popupLoader.item) && popupLoader.item.opacity == 0
+ interval: deallocationDelay
+ onTriggered: popupLoader.sourceComponent = undefined
+ }
+
+ states: State {
+ name: "active"
+ when: Qt.isQtObject(popupLoader.item) && popupLoader.item.opacity > 0
+ ParentChange { target: popupBehavior; parent: root }
+ }
+ }
+
diff --git a/components/custom/behaviors/TextEditMouseBehavior.qml b/components/custom/behaviors/TextEditMouseBehavior.qml
new file mode 100644
index 00000000..02175d5b
--- /dev/null
+++ b/components/custom/behaviors/TextEditMouseBehavior.qml
@@ -0,0 +1,266 @@
+import QtQuick 1.0
+
+// KNOWN ISSUES
+// 1) Can't tell if the Paste button should be shown or not, see QTBUG-16190
+// 2) Hard to tell if the Select button should be shown (part of QTBUG-16190?)
+
+Item {
+ id: mouseBehavior
+
+ property TextInput textInput
+ property TextEdit textEdit
+ property Flickable flickable
+ property bool desktopBehavior: true
+ property alias containsMouse: mouseArea.containsMouse
+
+ property Component copyPasteButtons
+
+ // Implementation
+
+ property Item textEditor: Qt.isQtObject(textInput) ? textInput : textEdit
+
+ Connections {
+ target: textInput
+ onTextChanged: reset()
+ onCursorPositionChanged: reset()
+ onSelectedTextChanged: reset()
+ onActiveFocusChanged: reset()
+ }
+
+ function reset() {
+ copyPastePopup.showing = false; // hide and restart the visibility timer
+ copyPastePopup.showing = selectedText.length > 0 && !desktopBehavior;
+ copyPastePopup.wasCancelledByClick = false;
+ copyPastePopup.wasClosedByCopy = false;
+ }
+
+ Component.onCompleted: {
+ textEditor.focus = true;
+ textEditor.selectByMouse = false;
+ textEditor.activeFocusOnPress = false;
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ drag.target: Item {} // work-around for Flickable stealing the mouse, which is expected (?), see QTBUG-15231
+
+ property int pressedPos
+ property int selectionStartAtPress
+ property int selectionEndAtPress
+ property bool hadFocusBeforePress
+ property bool draggingStartHandle
+ property bool draggingEndHandle
+
+ function characterPositionAt(mouse) {
+ var mappedMouse = mapToItem(textEditor, mouse.x, mouse.y);
+ if(Qt.isQtObject(textInput)) {
+ return textInput.positionAt(mappedMouse.x);
+ } else {
+ return textEdit.positionAt(mappedMouse.x, mappedMouse.y);
+ }
+ }
+
+ //mm see QTBUG-15814
+ onPressed: {
+ hadFocusBeforePress = textEditor.activeFocus;
+ selectionStartAtPress = textEditor.selectionStart;
+ selectionEndAtPress = textEditor.selectionEnd;
+
+ textEditor.forceActiveFocus(); //mm see QTBUG-16157
+ var pos = characterPositionAt(mouse);
+ if(desktopBehavior) {
+ textEditor.cursorPosition = pos;
+ } else {
+ draggingStartHandle = false; // reset both to false, i.e. no dragging of selection endpoints
+ draggingEndHandle = false;
+ if(textEditor.selectionStart != textEditor.selectionEnd) {
+ draggingEndHandle = (pos > selectionStartAtPress + (selectionEndAtPress-selectionStartAtPress)/2);
+ draggingStartHandle = !draggingEndHandle;
+ }
+ }
+
+ pressedPos = textEditor.cursorPosition;
+ }
+
+ onPressAndHold: {
+ if(!desktopBehavior) {
+ if(!textEditor.selectedText.length) { //mm Somehow just having the onPressAndHold impementation interrupts the text selection
+ textEditor.cursorPosition = characterPositionAt(mouse);
+ }
+ }
+ }
+
+ onReleased: {
+ if(!desktopBehavior) {
+ if(mouse.wasHeld) copyPastePopup.showing = true;
+ }
+ }
+
+ onClicked: {
+ if(!desktopBehavior) {
+ if(!hadFocusBeforePress)
+ return;
+
+ var pos = characterPositionAt(mouse);
+ if(textEditor.selectedText.length) { // clicked on or outside selection
+ if(copyPastePopup.wasClosedByCopy && pos >= textEditor.selectionStart && pos < textEditor.selectionEnd)
+ copyPastePopup.showing = true;
+ else
+ textEditor.select(textEditor.selectionEnd, textEditor.selectionEnd); //mm use deselect() from QtQuick 1.1 (see QTBUG-16059)
+ } else { // clicked while there's no selection
+ if(pos == textEditor.cursorPosition) { // Clicked where the cursor already where
+ copyPastePopup.showing = !copyPastePopup.wasCancelledByClick;
+ copyPastePopup.wasCancelledByClick = false;
+ } else { // Clicked in a new place (where the cursor wasn't)
+ var endOfWordRegEx = /[^\b]\b/g;
+ endOfWordRegEx.lastIndex = pos;
+ var endOfWordPosition = pos;
+ if(endOfWordRegEx.test(textEditor.text)) // updates lastIndex
+ endOfWordPosition = endOfWordRegEx.lastIndex;
+
+ if(textEditor.cursorPosition != endOfWordPosition) {
+ textEditor.cursorPosition = endOfWordPosition;
+ } else {
+ copyPastePopup.showing = !copyPastePopup.wasCancelledByClick;
+ copyPastePopup.wasCancelledByClick = false;
+ }
+ }
+ }
+ }
+
+ textEditor.openSoftwareInputPanel()
+ }
+
+ onPositionChanged: {
+ if(!pressed)
+ return;
+
+ var pos = characterPositionAt(mouse);
+ if(desktopBehavior) {
+ textEditor.select(pressedPos, pos);
+ } else {
+ if(draggingStartHandle) {
+ textEditor.select(selectionEndAtPress, pos);
+ } else if(draggingEndHandle) {
+ textEditor.select(selectionStartAtPress, pos);
+ } else if(mouse.wasHeld && textEditor.cursorPosition != pos) { // there's no selection
+ textEditor.cursorPosition = pos;
+ copyPastePopup.showing = true; // show once not pressed any more
+ }
+ }
+ }
+
+ onDoubleClicked: {
+ if(desktopBehavior)
+ textEditor.selectAll();
+ else {
+ textEditor.cursorPosition = characterPositionAt(mouse);
+ textEditor.selectWord(); // select word at cursor position
+ }
+ }
+ }
+
+
+ function selectionPopoutPoint() {
+ var point = {x:0, y:0}
+
+ var selectionStartRect = textEditor.positionToRectangle(textEditor.selectionStart);
+ var mappedStartPoint = mapFromItem(textEditor, selectionStartRect.x, selectionStartRect.y);
+ mappedStartPoint.x = Math.max(mappedStartPoint.x, 0);
+ mappedStartPoint.y = Math.max(mappedStartPoint.y, 0);
+
+ var selectioEndRect = textEditor.positionToRectangle(textEditor.selectionEnd);
+ var mappedEndPoint = mapFromItem(textEditor, selectioEndRect.x, selectioEndRect.y);
+ mappedEndPoint.x = Math.min(mappedEndPoint.x, textEditor.width);
+ mappedEndPoint.y = Math.min(mappedEndPoint.y, textEditor.height);
+
+ var multilineSelection = (selectionStartRect.y != selectioEndRect.y);
+ if(!multilineSelection) {
+ point.x = mappedStartPoint.x + (mappedEndPoint.x-mappedStartPoint.x)/2
+ } else {
+ point.x = textEditor.x + textEdit.width/2;
+ }
+
+ point.y = mappedStartPoint.y
+ return point;
+ }
+
+ Item {
+ id: copyPastePopup
+
+ property alias showing: modalPopup.showing
+ property bool wasCancelledByClick: false
+ property bool wasClosedByCopy: false
+
+ property bool showCopyAction: textEditor.selectedText.length > 0
+ property bool showCutAction: textEditor.selectedText.length > 0
+ property bool showPasteAction: true //textEditor.canPaste //mm see QTBUG-16190
+ property bool showSelectAction: textEditor.text.length > 0 && textEditor.selectedText.length < textEditor.text.length // need canSelectWord, see QTBUG-16190
+ property bool showSelectAllAction: textEditor.text.length > 0 && textEditor.selectedText.length < textEditor.text.length
+
+ ListModel {
+ id: popupButtonModel
+ ListElement { text: "Copy"; opacity: 0 } // index: 0
+ ListElement { text: "Cut"; opacity: 0 } // index: 1
+ ListElement { text: "Paste"; opacity: 1 } // index: 2
+ ListElement { text: "Select"; opacity: 0 } // index: 3
+ ListElement { text: "Select all"; opacity: 0 } // index: 4
+ }
+
+ onShowCopyActionChanged: popupButtonModel.setProperty(0, "opacity", showCopyAction ? 1 : 0);
+ onShowCutActionChanged: popupButtonModel.setProperty(1, "opacity", showCutAction ? 1 : 0);
+ onShowPasteActionChanged: popupButtonModel.setProperty(2, "opacity", showPasteAction ? 1 : 0);
+ onShowSelectActionChanged: popupButtonModel.setProperty(3, "opacity", showSelectAction ? 1 : 0);
+ onShowSelectAllActionChanged: popupButtonModel.setProperty(4, "opacity", showSelectAllAction ? 1 : 0);
+
+ Component.onCompleted: {
+ showCopyActionChanged();
+ showCutActionChanged();
+ showPasteActionChanged();
+ showSelectActionChanged();
+ showSelectAllActionChanged();
+ }
+
+ function positionPopout(popup, window) { // position poput above the text field's cursor
+ var popoutPoint = selectionPopoutPoint();
+ var mappedPos = mapToItem(window, popoutPoint.x, popoutPoint.y);
+ popup.x = Math.max(mappedPos.x - popup.width/2, 0);
+ if(popup.x+popup.width > window.width)
+ popup.x = window.width-popup.width;
+
+ popup.y = mappedPos.y - popup.height;
+ if(popup.y < 0)
+ popup.y += popup.height + textEditor.height;
+ }
+
+ ModalPopupBehavior {
+ id: modalPopup
+ consumeCancelClick: false
+ whenAlso: !mouseArea.pressed
+ delay: 300
+ onPrepareToShow: copyPastePopup.positionPopout(popup, window)
+ onCancelledByClick: copyPastePopup.wasCancelledByClick = true
+
+ popupComponent: copyPasteButtons
+ onPopupChanged: if(popup) popup.model = popupButtonModel
+
+ Connections {
+ target: modalPopup.popup
+ onClicked: {
+ if(index == 0) {
+ textEditor.copy();
+ copyPastePopup.showing = false;
+ copyPastePopup.wasClosedByCopy = true;
+ }
+ if(index == 1) textEditor.cut();
+ if(index == 2) textEditor.paste();
+ if(index == 3) textEditor.selectWord();
+ if(index == 4) textEditor.selectAll();
+ }
+ }
+ }
+ }
+}
+
diff --git a/components/custom/components.pro b/components/custom/components.pro
new file mode 100644
index 00000000..be0663d7
--- /dev/null
+++ b/components/custom/components.pro
@@ -0,0 +1,49 @@
+TEMPLATE = subdirs # XXX: Avoid call the linker
+TARGETPATH = Qt/labs/components/custom
+
+symbian {
+ INSTALL_IMPORTS = /resource/qt/imports
+} else {
+ INSTALL_IMPORTS = $$[QT_INSTALL_IMPORTS]
+}
+
+QML_FILES = \
+ qmldir \
+ BasicButton.qml \
+ BusyIndicator.qml \
+ ButtonBlock.qml \
+ ButtonColumn.qml \
+ ButtonRow.qml \
+ ButtonGroup.js \
+ Button.qml \
+ CheckBox.qml \
+ ChoiceList.qml \
+ ProgressBar.qml \
+ RadioButton.qml \
+ ScrollDecorator.qml \
+ ScrollIndicator.qml \
+ Slider.qml \
+ SpinBox.qml \
+ Switch.qml \
+ TextArea.qml \
+ TextField.qml
+
+QML_DIRS = \
+ behaviors \
+ private \
+ styles \
+ visuals
+
+qmlfiles.files = $$QML_FILES
+qmlfiles.sources = $$QML_FILES
+qmlfiles.path = $$INSTALL_IMPORTS/$$TARGETPATH
+
+qmldirs.files = $$QML_DIRS
+qmldirs.sources = $$QML_DIRS
+qmldirs.path = $$INSTALL_IMPORTS/$$TARGETPATH
+
+INSTALLS += qmlfiles qmldirs
+
+symbian {
+ DEPLOYMENT += qmlfiles qmldirs
+}
diff --git a/components/custom/private/ChoiceListPopup.qml b/components/custom/private/ChoiceListPopup.qml
new file mode 100644
index 00000000..61a0d222
--- /dev/null
+++ b/components/custom/private/ChoiceListPopup.qml
@@ -0,0 +1,269 @@
+import QtQuick 1.0
+
+MouseArea {
+ id: popup
+ // There is no global toplevel so we have to make one
+ // We essentially reparent this item to the root item
+ Component.onCompleted: {
+ var p = parent;
+ while (p.parent != undefined)
+ p = p.parent
+ parent = p;
+ }
+
+ anchors.fill: parent // fill the while app area
+ opacity: popupFrameLoader.item.opacity // let the frame control opacity, so it can set the behavior
+
+ property string behavior: "MacOS"
+ property bool desktopBehavior: (behavior == "MacOS" || behavior == "Windows" || behavior == "Linux")
+ property int previousCurrentIndex: -1 // set in state transition last in this file
+
+ property alias model: listView.model
+ property alias currentIndex: listView.currentIndex
+
+ property Component listItem
+ property Component listHighlight
+ property Component popupFrame
+
+ function togglePopup() { state = (state == "" ? "hidden" : "") }
+ function setCurrentIndex(index) { listView.currentIndex = index; }
+ function cancelSelection() { listView.currentIndex = previousCurrentIndex; }
+ function closePopup() { state = "hidden" }
+
+ function positionPopup() {
+ switch(behavior) {
+ case "MacOS":
+ var mappedListPos = mapFromItem(choiceList, 0, 0);
+ var itemHeight = Math.max(listView.contentHeight/listView.count, 0);
+ var currentItemY = Math.max(currentIndex*itemHeight, 0);
+ currentItemY += Math.floor(itemHeight/2 - choiceList.height/2); // correct for choiceLists that are higher than items in the list
+
+ listView.y = mappedListPos.y - currentItemY;
+ listView.x = mappedListPos.x;
+
+ listView.width = choiceList.width;
+ listView.height = listView.contentHeight //mm see QTBUG-16037
+
+ if(listView.y < topMargin) {
+ var excess = Math.floor(currentItemY - mappedListPos.y);
+ listView.y = topMargin;
+ listView.height += excess;
+ listView.contentY = excess + topMargin;
+
+ if(listView.contentY != excess+topMargin) //mm setting listView.height seems to make it worse
+ print("!!! ChoiceListPopup.qml: listView.contentY should be " + excess+topMargin + " but is " + listView.contentY)
+ }
+
+ if(listView.height+listView.contentY > listView.contentHeight) {
+ listView.height = listView.contentHeight-listView.contentY;
+ }
+
+ if(listView.y+listView.height+bottomMargin > popup.height) {
+ listView.height = popup.height-listView.y-bottomMargin;
+ }
+ break;
+ case "Windows":
+ var point = popup.mapFromItem(choiceList, 0, listView.height);
+ listView.y = point.y;
+ listView.x = point.x;
+
+ listView.width = choiceList.width;
+ listView.height = 200;
+
+ break;
+ case "MeeGo":
+ break;
+ }
+ }
+
+ Loader {
+ id: popupFrameLoader
+ property alias styledItem: popup.parent
+ anchors.fill: listView
+ anchors.leftMargin: -item.anchors.leftMargin
+ anchors.rightMargin: -item.anchors.rightMargin
+ anchors.topMargin: -item.anchors.topMargin
+ anchors.bottomMargin: -item.anchors.bottomMargin
+ sourceComponent: popupFrame
+ }
+
+ ListView {
+ id: listView
+ focus: true
+ boundsBehavior: desktopBehavior ? ListView.StopAtBounds : ListView.DragOverBounds
+ keyNavigationWraps: !desktopBehavior
+ highlightFollowsCurrentItem: false // explicitly handled below
+
+ interactive: !desktopBehavior // disable flicking. also disables key handling
+ onCurrentItemChanged: {
+ if(desktopBehavior) {
+ positionViewAtIndex(currentIndex, ListView.Contain);
+ }
+ }
+
+ property int highlightedIndex: -1
+ onHighlightedIndexChanged: positionViewAtIndex(highlightedIndex, ListView.Contain)
+
+ property variant highlightedItem: null
+ onHighlightedItemChanged: {
+ if(desktopBehavior) {
+ positionHighlight();
+ }
+ }
+
+ function positionHighlight() {
+ if(!Qt.isQtObject(highlightItem))
+ return;
+
+ if(!Qt.isQtObject(highlightedItem)) {
+ highlightItem.opacity = 0; // hide when no item is highlighted
+ } else {
+ highlightItem.x = highlightedItem.x;
+ highlightItem.y = highlightedItem.y;
+ highlightItem.width = highlightedItem.width;
+ highlightItem.height = highlightedItem.height;
+ highlightItem.opacity = 1; // show once positioned
+ }
+ }
+
+ function hideHighlight() {
+ highlightedIndex = -1;
+ highlightedItem = null; // will trigger positionHighlight() what will hide the highlight
+ }
+
+ delegate: Item {
+ id: itemDelegate
+ width: delegateLoader.item.width
+ height: delegateLoader.item.height
+ property int theIndex: index // for some reason the loader can't bind directly to the "index"
+
+ Loader {
+ id: delegateLoader
+ property variant model: listView.model
+ property alias index: itemDelegate.theIndex //mm Somehow the "model" gets through automagically, but not index
+ property Item styledItem: choiceList
+ property bool highlighted: theIndex == listView.highlightedIndex
+ sourceComponent: listItem
+ MouseArea { // handle list selection on mobile platforms
+ id:itemMouseArea
+ anchors.fill: parent
+ onClicked: { setCurrentIndex(index); closePopup(); }
+ }
+ }
+
+ states: State {
+ name: "highlighted"
+ when: index == listView.highlightedIndex
+ StateChangeScript {
+ script: {
+ if(Qt.isQtObject(listView.highlightedItem)) {
+ listView.highlightedItem.yChanged.disconnect(listView.positionHighlight);
+ }
+ listView.highlightedItem = itemDelegate;
+ listView.highlightedItem.yChanged.connect(listView.positionHighlight);
+ }
+ }
+
+ }
+ }
+
+ function firstVisibleItem() { return indexAt(contentX+10,contentY+10); }
+ function lastVisibleItem() { return indexAt(contentX+width-10,contentY+height-10); }
+ function itemsPerPage() { return lastVisibleItem() - firstVisibleItem(); }
+
+ Keys.onPressed: {
+ // with the ListView !interactive (non-flicking) we have to handle arrow keys
+ if (event.key == Qt.Key_Up) {
+ if(!highlightedItem) highlightedIndex = lastVisibleItem();
+ else if(highlightedIndex > 0) highlightedIndex--;
+ } else if (event.key == Qt.Key_Down) {
+ if(!highlightedItem) highlightedIndex = firstVisibleItem();
+ else if(highlightedIndex+1 < model.count) highlightedIndex++;
+ } else if (event.key == Qt.Key_PageUp) {
+ if(!highlightedItem) highlightedIndex = lastVisibleItem();
+ else highlightedIndex = Math.max(highlightedIndex-itemsPerPage(), 0);
+ } else if (event.key == Qt.Key_PageDown) {
+ if(!highlightedItem) highlightedIndex = firstVisibleItem();
+ else highlightedIndex = Math.min(highlightedIndex+itemsPerPage(), model.count-1);
+ } else if (event.key == Qt.Key_Home) {
+ highlightedIndex = 0;
+ } else if (event.key == Qt.Key_End) {
+ highlightedIndex = model.count-1;
+ } else if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return) {
+ if(highlightedIndex != -1) {
+ popup.setCurrentIndex(highlightedIndex);
+ } else {
+ popup.cancelSelection();
+ }
+
+ popup.closePopup();
+ } else if (event.key == Qt.Key_Escape) {
+ popup.cancelSelection();
+ popup.closePopup();
+ }
+ event.accepted = true; // consume all keys while popout has focus
+ }
+
+ highlight: popup.listHighlight
+ }
+
+ enabled: (state != "hidden") // to avoid stray events when poput is about to close
+ hoverEnabled: true
+ onClicked: { popup.cancelSelection(); popup.closePopup(); } // clicked outside the list
+ onPressed: {
+ var mappedPos = mapToItem(listView.contentItem, mouse.x, mouse.y);
+ var indexAt = listView.indexAt(mappedPos.x, mappedPos.y);
+ if(indexAt != -1) {
+ listView.currentIndex = indexAt;
+ }
+ }
+ onPositionChanged: {
+ var mappedPos = mapToItem(listView.contentItem, mouse.x, mouse.y);
+ var indexAt = listView.indexAt(mappedPos.x, mappedPos.y);
+ if(!pressed) { // hovering
+ if(indexAt == listView.highlightedIndex)
+ return;
+
+ if(indexAt >= 0) {
+ listView.highlightedIndex = indexAt;
+ } else {
+ if(mouse.y > listView.y+listView.height && listView.highlightedIndex+1 < listView.count ) {
+ listView.highlightedIndex++;
+ } else if(mouse.y < listView.y && listView.highlightedIndex > 0) {
+ listView.highlightedIndex--;
+ } else if(mouse.x < popupFrameLoader.x || mouse.x > popupFrameLoader.x+popupFrameLoader.width) {
+ listView.hideHighlight();
+ }
+ }
+ }
+ }
+
+ state: "hidden" // hidden by default
+ states: [
+ State {
+ name: "" // not hidden, i.e. showing
+ PropertyChanges { target: popupFrameLoader.item; opacity: 1 }
+ },
+ State {
+ name: "hidden"
+ PropertyChanges { target: popupFrameLoader.item; opacity: 0 }
+ }
+ ]
+
+ transitions: [
+ Transition { to: "";
+ ScriptAction {
+ script: {
+ previousCurrentIndex = currentIndex;
+ positionPopup();
+ listView.forceActiveFocus();
+ }
+ }
+ },
+ Transition { to: "hidden"; ScriptAction { script: listView.hideHighlight(); } }
+ ]
+}
+
+
+
+
diff --git a/components/custom/qmldir b/components/custom/qmldir
new file mode 100644
index 00000000..6e256a81
--- /dev/null
+++ b/components/custom/qmldir
@@ -0,0 +1,17 @@
+BasicButton 1.0 BasicButton.qml
+BusyIndicator 1.0 BusyIndicator.qml
+ButtonBlock 1.0 ButtonBlock.qml
+Button 1.0 Button.qml
+ButtonColumn 1.0 ButtonColumn.qml
+ButtonRow 1.0 ButtonRow.qml
+CheckBox 1.0 CheckBox.qml
+ChoiceList 1.0 ChoiceList.qml
+ProgressBar 1.0 ProgressBar.qml
+RadioButton 1.0 RadioButton.qml
+ScrollDecorator 1.0 ScrollDecorator.qml
+ScrollIndicator 1.0 ScrollIndicator.qml
+Slider 1.0 Slider.qml
+SpinBox 1.0 SpinBox.qml
+Switch 1.0 Switch.qml
+TextArea 1.0 TextArea.qml
+TextField 1.0 TextField.qml
diff --git a/components/custom/styles/default/BasicButtonStyle.qml b/components/custom/styles/default/BasicButtonStyle.qml
new file mode 100644
index 00000000..08b18040
--- /dev/null
+++ b/components/custom/styles/default/BasicButtonStyle.qml
@@ -0,0 +1,8 @@
+import QtQuick 1.1
+
+QtObject {
+ property int minimumWidth: 40
+ property int minimumHeight: 25
+
+ property Component background: Component { Item { } }
+}
diff --git a/components/custom/styles/default/BusyIndicatorStyle.qml b/components/custom/styles/default/BusyIndicatorStyle.qml
new file mode 100644
index 00000000..83ef46fd
--- /dev/null
+++ b/components/custom/styles/default/BusyIndicatorStyle.qml
@@ -0,0 +1,21 @@
+import QtQuick 1.0
+
+QtObject {
+ property Component background:
+ Component {
+ Image {
+ opacity: running ? 1.0 : 0.7 //mm Should the rotation fade and stop when indicator is !enabled?
+ source: "images/spinner.png";
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+
+ property int steps: 12
+ property int rotationStep: 0
+ rotation: rotationStep*(360/steps)
+ NumberAnimation on rotationStep {
+ running: busyIndicator.running; from: 0; to: steps; //mm see QTBUG-15652
+ loops: Animation.Infinite; duration: 1000 // 1s per revolution
+ }
+ }
+ }
+}
diff --git a/components/custom/styles/default/ButtonBlockStyle.qml b/components/custom/styles/default/ButtonBlockStyle.qml
new file mode 100644
index 00000000..f0bed865
--- /dev/null
+++ b/components/custom/styles/default/ButtonBlockStyle.qml
@@ -0,0 +1,77 @@
+import QtQuick 1.0
+
+QtObject {
+ property int minimumWidth: 90
+ property int minimumHeight: 32
+
+ property int leftMargin : 8
+ property int topMargin: 8
+ property int rightMargin: 8
+ property int bottomMargin: 8
+
+ property Component background:
+ Component {
+ id: defaultBackground
+ Item {
+ opacity: enabled ? 1 : 0.7
+ Rectangle { // Background center fill
+ anchors.fill: parent
+ anchors.leftMargin: adjoining&Qt.Horizontal ? 0 : 2
+ anchors.rightMargin: anchors.leftMargin
+ anchors.topMargin: adjoining&Qt.Vertical ? 0 : 2
+ anchors.bottomMargin: anchors.topMargin
+
+ radius: adjoining ? 0 : 5
+ color: !styledItem.checked ? backgroundColor : Qt.darker(backgroundColor)
+ }
+ BorderImage {
+ anchors.fill: parent
+ smooth: true
+ source: {
+ if(!adjoining)
+ return styledItem.pressed || styledItem.checked ? "images/button_pressed.png" : "images/button_normal.png";
+ else if(adjoining&Qt.Horizontal)
+ return styledItem.pressed || styledItem.checked ? "images/buttongroup_h_pressed.png" : "images/buttongroup_h_normal.png";
+ else // adjoining&Qt.Vertical
+ return styledItem.pressed || styledItem.checked ? "images/buttongroup_v_pressed.png" : "images/buttongroup_v_normal.png";
+ }
+ border.left: 6; border.top: 6
+ border.right: 6; border.bottom: 6
+ }
+ }
+ }
+
+ property Component label:
+ Component {
+ id: defaultLabel
+ Item {
+ width: row.width
+ height: row.height
+ anchors.centerIn: parent //mm see QTBUG-15619
+ opacity: styledItem.enabled ? 1 : 0.5
+ transform: Translate {
+ x: styledItem.pressed || styledItem.checked ? 1 : 0
+ y: styledItem.pressed || styledItem.checked ? 1 : 0
+ }
+
+ Row {
+ id: row
+ anchors.centerIn: parent
+ spacing: 4
+ Image {
+ source: styledItem.iconSource
+ anchors.verticalCenter: parent.verticalCenter
+ fillMode: Image.Stretch //mm Image should shrink if button is too small, depends on QTBUG-14957
+ }
+
+ Text {
+ color: styledItem.textColor
+ anchors.verticalCenter: parent.verticalCenter
+ text: styledItem.text
+ horizontalAlignment: Text.Center
+ elide: Text.ElideRight //mm can't make layout work as desired without implicit size support, see QTBUG-14957
+ }
+ }
+ }
+ }
+}
diff --git a/components/custom/styles/default/ButtonStyle.qml b/components/custom/styles/default/ButtonStyle.qml
new file mode 100644
index 00000000..a0e5f330
--- /dev/null
+++ b/components/custom/styles/default/ButtonStyle.qml
@@ -0,0 +1,102 @@
+import QtQuick 1.1
+
+QtObject {
+ property int minimumWidth: 90
+ property int minimumHeight: 32
+
+ property int leftMargin: 8
+ property int topMargin: 8
+ property int rightMargin: 8
+ property int bottomMargin: 8
+
+ property Component background: Component {
+ Item {
+ opacity: enabled ? 1 : 0.7
+ clip: true // clip connected buttons, as they overlap to remove the rounded edjes
+ property bool isPositioned: position != "only" // only evaluate for rows and columns
+
+ Item {
+ anchors.fill: parent
+ // Give connected buttons a negative styling margin, to make
+ // them overlap and the rounded edge can be clipped away
+ anchors.leftMargin: isPositioned && (position == "rightmost" || position =="h_middle") ? -leftMargin : 0
+ anchors.rightMargin: isPositioned && (position == "leftmost" || position =="h_middle") ? -rightMargin : 0
+ anchors.topMargin: isPositioned && (position == "bottom" || position =="v_middle") ? -bottomMargin : 0
+ anchors.bottomMargin: isPositioned && (position == "top" || position =="v_middle") ? -topMargin : 0
+
+ Rectangle { // Background center fill
+ anchors.fill: parent
+ anchors.leftMargin: anchors.leftMargin
+ anchors.rightMargin: anchors.rightMargin
+ anchors.topMargin: anchors.topMargin
+ anchors.bottomMargin: anchors.bottomMargin
+ radius: 5
+ color: backgroundColor
+ }
+ BorderImage {
+ anchors.fill: parent
+ smooth: true
+ source: pressed || checked ? "images/button_pressed.png" : "images/button_normal.png";
+ border.left: 6; border.top: 6
+ border.right: 6; border.bottom: 6
+ }
+ }
+
+ // Draw straight border lines between connected buttons
+ Rectangle {
+ width: 1
+ visible: isPositioned && !checked && !pressed && (position == "rightmost" || position == "h_middle")
+ anchors.top: parent.top
+ anchors.topMargin: 2
+ anchors.bottomMargin: 2
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ opacity: 0.4
+ color: "white"
+ }
+ Rectangle {
+ width: 1
+ opacity: 0.4
+ visible: isPositioned && !checked && !pressed && (position == "leftmost" || position == "h_middle")
+ anchors.top: parent.top
+ anchors.topMargin: 2
+ anchors.bottomMargin: 2
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ color: "black"
+ }
+ }
+ }
+
+ property Component label: Component {
+ Item {
+ implicitWidth: row.implicitWidth
+ implicitHeight: row.implicitHeight
+
+ opacity: enabled ? 1 : 0.5
+ transform: Translate {
+ x: pressed || checked ? 1 : 0
+ y: pressed || checked ? 1 : 0
+ }
+
+ Row {
+ id: row
+ anchors.centerIn: parent
+ spacing: 4
+ Image {
+ source: iconSource
+ anchors.verticalCenter: parent.verticalCenter
+ fillMode: Image.Stretch //mm Image should shrink if button is too small, depends on QTBUG-14957
+ }
+
+ Text {
+ color: textColor
+ anchors.verticalCenter: parent.verticalCenter
+ text: styledItem.text
+ horizontalAlignment: Text.Center
+ elide: Text.ElideRight //mm can't make layout work as desired without implicit size support, see QTBUG-14957
+ }
+ }
+ }
+ }
+}
diff --git a/components/custom/styles/default/CheckBoxStyle.qml b/components/custom/styles/default/CheckBoxStyle.qml
new file mode 100644
index 00000000..f5e5fdde
--- /dev/null
+++ b/components/custom/styles/default/CheckBoxStyle.qml
@@ -0,0 +1,34 @@
+import QtQuick 1.1
+
+QtObject {
+ property int minimumWidth: 32
+ property int minimumHeight: 32
+
+ property Component background: Component {
+ Item {
+ width: styledItem.implicitWidth; height: styledItem.implicitHeight
+ opacity: enabled ? 1 : 0.7
+ Rectangle { // Background center fill
+ anchors.fill: parent
+ anchors.margins: 1
+ radius: 5
+ color: backgroundColor
+ }
+ BorderImage {
+ anchors.fill: parent
+ source: "images/lineedit_normal.png"
+ smooth: true
+ border.left: 6; border.top: 3
+ border.right: 6; border.bottom: 3
+ }
+ }
+ }
+
+ property Component checkmark: Component {
+ Image {
+ source: "images/checkbox_check.png"
+ opacity: (!enabled && checked) || pressed == true ? 0.5 : (!checked ? 0 : 1)
+ Behavior on opacity { NumberAnimation { duration: 150; easing.type: Easing.OutCubic } }
+ }
+ }
+}
diff --git a/components/custom/styles/default/ChoiceListStyle.qml b/components/custom/styles/default/ChoiceListStyle.qml
new file mode 100644
index 00000000..12b10ffd
--- /dev/null
+++ b/components/custom/styles/default/ChoiceListStyle.qml
@@ -0,0 +1,100 @@
+import QtQuick 1.0
+
+QtObject {
+ property int minimumWidth: 200
+ property int minimumHeight: 32
+
+ property int leftMargin: 8
+ property int topMargin: 8
+ property int rightMargin: 34
+ property int bottomMargin: 8
+
+ property Component background: Component {
+ Item {
+ opacity: enabled ? 1 : 0.8
+ Rectangle { // Background center fill
+ anchors.fill: parent
+ anchors.margins: 1
+ color: backgroundColor
+ radius: 5
+ }
+ BorderImage {
+ anchors.fill: parent
+ id: backgroundimage
+ smooth: true
+ source: styledItem.pressed ? "images/button_pressed.png" : "images/button_normal.png"
+ width: 80; height: 24
+ border.left: 3; border.top: 3
+ border.right: 3; border.bottom: 3
+ Image {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ opacity: enabled ? 1 : 0.3
+ source:"images/spinbox_down.png"
+ }
+ }
+ }
+ }
+
+ property Component label: Component {
+ Text {
+ id:t
+ color: textColor
+ text: model && currentIndex >= 0 ? model.get(currentIndex).text : ""
+ opacity: enabled ? 1 : 0.5
+ }
+ }
+
+ // Popout styling
+
+ property Component popupFrame: Component {
+ Item {
+ Behavior on opacity { NumberAnimation { easing.type: Easing.OutQuad; duration: 250 } }
+
+ anchors.leftMargin: 6
+ anchors.topMargin: 6
+ anchors.rightMargin: 7
+ anchors.bottomMargin: 6
+
+ Rectangle { // Background center fill
+ anchors.fill: parent
+ anchors.margins: 1
+ color: backgroundColor
+ radius: 5
+ }
+ BorderImage {
+ anchors.fill: parent
+ id: backgroundimage
+ smooth: true
+ source: "images/button_normal.png"
+ width: 80; height: 24
+ border.left: 5; border.top: 5
+ border.right: 5; border.bottom: 5
+ }
+ }
+ }
+
+ property Component listItem: Component {
+ Rectangle {
+ width: styledItem.width
+ height: Math.max(itemText.height, 28)
+ color: highlighted ? "#556699" : "transparent"
+ radius:2
+ border.width:1
+ border.color:Qt.darker(color)
+ clip:true
+ Text {
+ id: itemText
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 6
+
+ font.bold: index == currentIndex
+ color: highlighted ? "white" : styledItem.textColor
+ anchors.margins: 10
+ text: model ? model.get(index).text : "" // list properties can't be automatically be added to the scope, so use get()
+ }
+ }
+ }
+}
diff --git a/components/custom/styles/default/ProgressBarStyle.qml b/components/custom/styles/default/ProgressBarStyle.qml
new file mode 100644
index 00000000..7cb9795c
--- /dev/null
+++ b/components/custom/styles/default/ProgressBarStyle.qml
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Components project on Qt Labs.
+**
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions contained
+** in the Technology Preview License Agreement accompanying this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+QtObject {
+ property int minimumWidth: 200
+ property int minimumHeight: 25
+
+ property int leftMargin: 0
+ property int rightMargin: 0
+ property int topMargin: 0
+ property int bottomMargin: 0
+
+ property Component background: Component {
+ Item{
+ Rectangle{
+ anchors.fill:parent
+ width: parent.width-2
+ height: parent.height-2
+ color: backgroundColor
+ radius: 5
+ }
+ BorderImage {
+ anchors.fill:parent
+ source:"images/progressbar_groove.png"
+ border.left:10; border.right:10
+ border.top:10; border.bottom:10
+ }
+ }
+ }
+
+ property Component progress: Component { // progress bar, known duration
+ BorderImage { // green progress indication
+ id:progress
+ opacity: styledItem.enabled ? 1: 0.7
+ source: complete > 0.95 ?
+ "images/progressbar_indeterminate.png" : "images/progressbar_fill.png"
+ border.left:complete > 0.1 ? 6: 2;
+ border.right:complete > 0.1 ? 6: 2
+ border.top:10; border.bottom:10
+ clip:true
+
+ Rectangle{
+ anchors.fill:progress
+ color: styledItem.progressColor
+ z:-1
+ radius:2
+ smooth:true
+ clip:true
+ anchors.rightMargin:0
+ anchors.margins:1
+ Image {
+ id: overlay
+ NumberAnimation on x {
+ loops:Animation.Infinite;
+ from:0;
+ to:-overlay.sourceSize.width;
+ duration:2000
+ }
+ width:styledItem.width + sourceSize.width
+ height:styledItem.height
+ fillMode:Image.Tile
+ source: "images/progressbar_overlay.png"
+ }
+ }
+ }
+ }
+
+ property Component indeterminateProgress: Component { // progress bar, unknown duration
+ Item {
+ id: bar
+ anchors.fill:parent
+ onWidthChanged:indicator.x = width-indicator.width
+ BorderImage {
+ id:indicator
+ opacity: styledItem.enabled ? 1: 0.7
+ Behavior on x {
+ NumberAnimation{easing.type:Easing.Linear; duration:1000}
+ }
+ onXChanged: {
+ var w = bar.width - indicator.width
+ if (x == w) x = 0
+ else if (x==0) x = w
+ }
+ width: 80
+ height: parent.height
+ source:"images/progressbar_indeterminate.png"
+ border.left:10 ; border.right:10
+ border.top:10 ; border.bottom:10
+ clip:true
+
+ Rectangle{
+ anchors.fill:indicator
+ color: styledItem.progressColor
+ z:-1
+ radius:2
+ smooth:true
+ clip:true
+ anchors.rightMargin:0
+ anchors.margins:1
+ Image {
+ id: overlay
+ NumberAnimation on x {
+ loops:Animation.Infinite;
+ from:0;
+ to:-overlay.sourceSize.width;
+ duration:2000
+ }
+ width:styledItem.width + sourceSize.width
+ height:styledItem.height
+ fillMode:Image.Tile
+ source: "images/progressbar_overlay.png"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/components/custom/styles/default/RadioButtonStyle.qml b/components/custom/styles/default/RadioButtonStyle.qml
new file mode 100644
index 00000000..0381993e
--- /dev/null
+++ b/components/custom/styles/default/RadioButtonStyle.qml
@@ -0,0 +1,34 @@
+import QtQuick 1.1
+import "tools" as StyleTools
+
+QtObject {
+ property int minimumWidth: 32
+ property int minimumHeight: 32
+
+ property Component background: Component {
+ Item {
+ width: styledItem.implicitWidth; height: styledItem.implicitHeight
+ Rectangle { // Background center fill
+ anchors.fill: parent
+ anchors.margins: 1
+ radius: width/2
+ color: backgroundColor
+ }
+ Image {
+ opacity: enabled ? 1 : 0.7
+ source: "images/radiobutton_normal.png"
+ fillMode: Image.Stretch
+ anchors.centerIn: parent
+ }
+ }
+ }
+
+ property Component checkmark: Component {
+ Image {
+ StyleTools.ColorConverter { id: cc; color: backgroundColor }
+ source: cc.grayValue() < 70? "images/radiobutton_check_white.png" : "images/radiobutton_check.png"
+ opacity: (!enabled && checked) || pressed == true ? 0.5 : (!checked ? 0 : 1)
+ Behavior on opacity { NumberAnimation { duration: 150; easing.type: Easing.OutCubic } }
+ }
+ }
+}
diff --git a/components/custom/styles/default/ScrollIndicatorStyle.qml b/components/custom/styles/default/ScrollIndicatorStyle.qml
new file mode 100644
index 00000000..8e8826cd
--- /dev/null
+++ b/components/custom/styles/default/ScrollIndicatorStyle.qml
@@ -0,0 +1,18 @@
+import QtQuick 1.0
+
+QtObject {
+ property int minimumWidth: 12
+ property int minimumHeight: 40
+
+ property Component content: Component {
+ Item {
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 3
+ border.color: "black"
+ color: "gray"
+ radius: width/2
+ }
+ }
+ }
+}
diff --git a/components/custom/styles/default/SliderStyle.qml b/components/custom/styles/default/SliderStyle.qml
new file mode 100644
index 00000000..d32f13eb
--- /dev/null
+++ b/components/custom/styles/default/SliderStyle.qml
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Components project on Qt Labs.
+**
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions contained
+** in the Technology Preview License Agreement accompanying this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+QtObject {
+
+ property int minimumWidth: 200
+ property int minimumHeight: 40
+
+ property int leftMargin : 2
+ property int topMargin: 0
+ property int rightMargin: 2
+ property int bottomMargin: 0
+
+ property Component groove: Item {
+ opacity: enabled ? 1.0 : 0.7
+
+ Rectangle {
+ color: backgroundColor
+ anchors.fill: sliderBackground
+ anchors.margins: 1
+ radius: 2
+ }
+
+ Rectangle {
+ property real zeroPos : positionForValue(0)
+ property real handlePos: handlePosition
+ color: progressColor
+ height: 10
+ radius: 4
+ anchors.verticalCenter: parent.verticalCenter
+ x: zeroPos
+ width: handlePos - x
+ }
+
+ BorderImage {
+ id: sliderBackground
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width
+ border.top: 2
+ border.bottom: 2
+ border.left: 12
+ border.right: 12
+ source: "images/slider.png"
+ }
+ }
+
+ property Component handle: Item {
+ width: handleImage.width
+ height: handleImage.height
+ anchors.verticalCenter: parent.verticalCenter
+
+ Image {
+ id: handleImage
+ Rectangle {
+ anchors.centerIn: parent
+ anchors.horizontalCenterOffset: -1
+ width: parent.width - 7
+ height: parent.height - 7
+ smooth: true
+ color: backgroundColor
+ radius: Math.floor(parent.width / 2)
+ z: -1 // behind the image
+ }
+ anchors.centerIn: parent;
+ source: "images/handle.png"
+ smooth: true
+ }
+ }
+
+ property Component valueIndicator: Rectangle {
+ width: valueText.width + 20
+ height: valueText.height + 20
+ color: "gray"
+ opacity: pressed ? 0.9 : 0
+ Behavior on opacity { NumberAnimation { duration: 100 } }
+ radius: 5
+
+ Text {
+ id: valueText
+ anchors.margins: 10
+ anchors.centerIn: parent
+ text: indicatorText
+ }
+ }
+}
diff --git a/components/custom/styles/default/SpinBoxStyle.qml b/components/custom/styles/default/SpinBoxStyle.qml
new file mode 100644
index 00000000..d42267d8
--- /dev/null
+++ b/components/custom/styles/default/SpinBoxStyle.qml
@@ -0,0 +1,73 @@
+import QtQuick 1.0
+
+QtObject {
+
+ property int minimumWidth: 200
+ property int minimumHeight: 25
+
+ property int leftMargin : 8
+ property int topMargin: 8
+ property int rightMargin: 8
+ property int bottomMargin: 8
+
+ property Component background:
+ Component {
+ id: defaultBackground
+ Item {
+ opacity: enabled ? 1 : 0.7
+ Rectangle {
+ x: 1
+ y: 1
+ width: parent.width-2
+ height: parent.height-2
+ color: backgroundColor
+ radius: 5
+ }
+
+ BorderImage {
+ anchors.fill: parent
+ id: backgroundimage
+ smooth: true
+ source: "images/lineedit_normal.png"
+ border.left: 6; border.top: 6
+ border.right: 50; border.bottom: 6
+ }
+ }
+ }
+
+ property Component up:
+ Component {
+ id: defaultUp
+ Item {
+ anchors.right: parent.right
+ anchors.top: parent.top
+ width: 24
+ height: parent.height/2
+ Image {
+ anchors.left: parent.left;
+ anchors.top: parent.top;
+ anchors.topMargin: 7
+ opacity: (upEnabled && enabled) ? (upPressed ? 1 : 0.8) : 0.3
+ source: "images/spinbox_up.png"
+ }
+ }
+ }
+
+ property Component down:
+ Component {
+ id: defaultDown
+ Item {
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ width: 24
+ height: parent.height/2
+ Image {
+ anchors.left: parent.left;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 7
+ opacity: (downEnabled && enabled) ? (downPressed ? 1 : 0.8) : 0.3
+ source: "images/spinbox_down.png"
+ }
+ }
+ }
+}
diff --git a/components/custom/styles/default/SwitchStyle.qml b/components/custom/styles/default/SwitchStyle.qml
new file mode 100644
index 00000000..35e6f235
--- /dev/null
+++ b/components/custom/styles/default/SwitchStyle.qml
@@ -0,0 +1,71 @@
+import QtQuick 1.1
+
+QtObject {
+ property int minimumWidth: 80
+ property int minimumHeight: 32
+
+ property Component groove: Component {
+ Item {
+ opacity: enabled ? 1 : 0.7
+ Rectangle { // Background center fill
+ anchors.fill: parent
+ anchors.margins: 1
+ radius: 5
+ color: backgroundColor
+ }
+
+ Item { // Clipping container of the positive and negative groove highlight
+ anchors.fill: parent
+ anchors.margins: 2
+ clip: true
+
+ Item { // The highlight item is twice the width of there switch, clipped by its parent,
+ // and sliding back and forth keeping the center under the handle
+ height: parent.height
+ width: 2*parent.width
+ x: handleCenterX-parent.width-parent.anchors.leftMargin
+
+ Rectangle { // positive background highlight
+ color: positiveHighlightColor
+ opacity: 0.8
+ anchors.top: parent.top; anchors.bottom: parent.bottom
+ anchors.left: parent.left; anchors.right: parent.horizontalCenter
+ }
+ Rectangle { // negative background highlight
+ color: negativeHighlightColor
+ opacity: 0.8
+ anchors.top: parent.top; anchors.bottom: parent.bottom
+ anchors.left: parent.horizontalCenter; anchors.right: parent.right
+ }
+ }
+ }
+
+ BorderImage { // Rounded border
+ anchors.fill: parent
+ source: "images/lineedit_normal.png"
+ border { left: 6; right: 6; top: 3; bottom: 3 }
+ smooth: true
+ }
+ }
+ }
+
+ property Component handle: Component {
+ Item {
+ width: 42
+ Rectangle { // center fill
+ anchors.fill: parent
+ anchors.margins: 1
+ radius: 5
+ color: switchColor
+ }
+ BorderImage {
+ anchors.fill: parent
+ opacity: enabled ? 1 : 0.7
+ smooth: true
+ source: pressed ? "images/button_pressed.png" : "images/button_normal.png"
+ border { left: 4; top: 4; right: 4; bottom: 4 }
+ }
+ Behavior on x { NumberAnimation { easing.type: Easing.OutCubic; duration: 200 } }
+ }
+ }
+}
diff --git a/components/custom/styles/default/TextFieldStyle.qml b/components/custom/styles/default/TextFieldStyle.qml
new file mode 100644
index 00000000..38da6b0d
--- /dev/null
+++ b/components/custom/styles/default/TextFieldStyle.qml
@@ -0,0 +1,41 @@
+import QtQuick 1.0
+
+QtObject {
+
+ property int minimumWidth: 200
+ property int minimumHeight: 25
+
+ property int leftMargin : 8
+ property int topMargin: 8
+ property int rightMargin: 8
+ property int bottomMargin: 8
+
+ property Component background: Component {
+ Item { // see QTBUG-14873
+ Rectangle { // Background center fill
+ anchors.fill: parent
+ anchors.margins: 1
+ radius: 5
+ color: backgroundColor
+ }
+ BorderImage { // Background border
+ opacity: enabled ? 1 : 0.7
+ anchors.fill: parent
+ border.left: 6; border.top: 6
+ border.right: 6; border.bottom: 6
+ smooth: true
+ source: "images/lineedit_normal.png"
+ }
+ }
+ }
+
+ property Component hints: Component {
+ Item {
+ property color textColor: "#444"
+ property color backgroundColor: "white"
+ property int fontPixelSize: 14
+ property bool fontBold: false
+ property int passwordEchoMode: TextInput.PasswordEchoOnEdit
+ }
+ }
+}
diff --git a/components/custom/styles/default/images/button_normal.png b/components/custom/styles/default/images/button_normal.png
new file mode 100644
index 00000000..e54f1acb
--- /dev/null
+++ b/components/custom/styles/default/images/button_normal.png
Binary files differ
diff --git a/components/custom/styles/default/images/button_pressed.png b/components/custom/styles/default/images/button_pressed.png
new file mode 100644
index 00000000..b7a63f1a
--- /dev/null
+++ b/components/custom/styles/default/images/button_pressed.png
Binary files differ
diff --git a/components/custom/styles/default/images/buttongroup_h_normal.png b/components/custom/styles/default/images/buttongroup_h_normal.png
new file mode 100644
index 00000000..bae59381
--- /dev/null
+++ b/components/custom/styles/default/images/buttongroup_h_normal.png
Binary files differ
diff --git a/components/custom/styles/default/images/buttongroup_h_pressed.png b/components/custom/styles/default/images/buttongroup_h_pressed.png
new file mode 100644
index 00000000..e0c97fd5
--- /dev/null
+++ b/components/custom/styles/default/images/buttongroup_h_pressed.png
Binary files differ
diff --git a/components/custom/styles/default/images/checkbox_check.png b/components/custom/styles/default/images/checkbox_check.png
new file mode 100644
index 00000000..a2f1f02d
--- /dev/null
+++ b/components/custom/styles/default/images/checkbox_check.png
Binary files differ
diff --git a/components/custom/styles/default/images/handle.png b/components/custom/styles/default/images/handle.png
new file mode 100644
index 00000000..bd8fbddf
--- /dev/null
+++ b/components/custom/styles/default/images/handle.png
Binary files differ
diff --git a/components/custom/styles/default/images/lineedit_normal.png b/components/custom/styles/default/images/lineedit_normal.png
new file mode 100644
index 00000000..2253d33f
--- /dev/null
+++ b/components/custom/styles/default/images/lineedit_normal.png
Binary files differ
diff --git a/components/custom/styles/default/images/progress-bar-background.png b/components/custom/styles/default/images/progress-bar-background.png
new file mode 100644
index 00000000..4f30927e
--- /dev/null
+++ b/components/custom/styles/default/images/progress-bar-background.png
Binary files differ
diff --git a/components/custom/styles/default/images/progress-bar-bar.png b/components/custom/styles/default/images/progress-bar-bar.png
new file mode 100644
index 00000000..446c13f2
--- /dev/null
+++ b/components/custom/styles/default/images/progress-bar-bar.png
Binary files differ
diff --git a/components/custom/styles/default/images/progressbar_fill.png b/components/custom/styles/default/images/progressbar_fill.png
new file mode 100644
index 00000000..0f877896
--- /dev/null
+++ b/components/custom/styles/default/images/progressbar_fill.png
Binary files differ
diff --git a/components/custom/styles/default/images/progressbar_groove.png b/components/custom/styles/default/images/progressbar_groove.png
new file mode 100644
index 00000000..263ced8b
--- /dev/null
+++ b/components/custom/styles/default/images/progressbar_groove.png
Binary files differ
diff --git a/components/custom/styles/default/images/progressbar_indeterminate.png b/components/custom/styles/default/images/progressbar_indeterminate.png
new file mode 100644
index 00000000..7ea46460
--- /dev/null
+++ b/components/custom/styles/default/images/progressbar_indeterminate.png
Binary files differ
diff --git a/components/custom/styles/default/images/progressbar_overlay.png b/components/custom/styles/default/images/progressbar_overlay.png
new file mode 100644
index 00000000..8e351f96
--- /dev/null
+++ b/components/custom/styles/default/images/progressbar_overlay.png
Binary files differ
diff --git a/components/custom/styles/default/images/qt-logo.png b/components/custom/styles/default/images/qt-logo.png
new file mode 100644
index 00000000..005ee5ca
--- /dev/null
+++ b/components/custom/styles/default/images/qt-logo.png
Binary files differ
diff --git a/components/custom/styles/default/images/radiobutton_check.png b/components/custom/styles/default/images/radiobutton_check.png
new file mode 100644
index 00000000..3d433860
--- /dev/null
+++ b/components/custom/styles/default/images/radiobutton_check.png
Binary files differ
diff --git a/components/custom/styles/default/images/radiobutton_check_white.png b/components/custom/styles/default/images/radiobutton_check_white.png
new file mode 100644
index 00000000..b68e7a69
--- /dev/null
+++ b/components/custom/styles/default/images/radiobutton_check_white.png
Binary files differ
diff --git a/components/custom/styles/default/images/radiobutton_normal.png b/components/custom/styles/default/images/radiobutton_normal.png
new file mode 100644
index 00000000..6ceab7ee
--- /dev/null
+++ b/components/custom/styles/default/images/radiobutton_normal.png
Binary files differ
diff --git a/components/custom/styles/default/images/slider-background.png b/components/custom/styles/default/images/slider-background.png
new file mode 100644
index 00000000..3ba9c473
--- /dev/null
+++ b/components/custom/styles/default/images/slider-background.png
Binary files differ
diff --git a/components/custom/styles/default/images/slider-handle-active.png b/components/custom/styles/default/images/slider-handle-active.png
new file mode 100644
index 00000000..83cec3f4
--- /dev/null
+++ b/components/custom/styles/default/images/slider-handle-active.png
Binary files differ
diff --git a/components/custom/styles/default/images/slider-handle.png b/components/custom/styles/default/images/slider-handle.png
new file mode 100644
index 00000000..765e610a
--- /dev/null
+++ b/components/custom/styles/default/images/slider-handle.png
Binary files differ
diff --git a/components/custom/styles/default/images/slider.png b/components/custom/styles/default/images/slider.png
new file mode 100644
index 00000000..3f310e37
--- /dev/null
+++ b/components/custom/styles/default/images/slider.png
Binary files differ
diff --git a/components/custom/styles/default/images/spinbox_down.png b/components/custom/styles/default/images/spinbox_down.png
new file mode 100644
index 00000000..a6f3f79e
--- /dev/null
+++ b/components/custom/styles/default/images/spinbox_down.png
Binary files differ
diff --git a/components/custom/styles/default/images/spinbox_up.png b/components/custom/styles/default/images/spinbox_up.png
new file mode 100644
index 00000000..a4841941
--- /dev/null
+++ b/components/custom/styles/default/images/spinbox_up.png
Binary files differ
diff --git a/components/custom/styles/default/images/spinner.png b/components/custom/styles/default/images/spinner.png
new file mode 100644
index 00000000..664c2b14
--- /dev/null
+++ b/components/custom/styles/default/images/spinner.png
Binary files differ
diff --git a/components/custom/styles/default/images/switch_normal.png b/components/custom/styles/default/images/switch_normal.png
new file mode 100644
index 00000000..ac46b211
--- /dev/null
+++ b/components/custom/styles/default/images/switch_normal.png
Binary files differ
diff --git a/components/custom/styles/default/images/switch_pressed.png b/components/custom/styles/default/images/switch_pressed.png
new file mode 100644
index 00000000..a04a3f4b
--- /dev/null
+++ b/components/custom/styles/default/images/switch_pressed.png
Binary files differ
diff --git a/components/custom/styles/default/tools/ColorConverter.qml b/components/custom/styles/default/tools/ColorConverter.qml
new file mode 100644
index 00000000..5070ff1e
--- /dev/null
+++ b/components/custom/styles/default/tools/ColorConverter.qml
@@ -0,0 +1,59 @@
+import QtQuick 1.0
+
+// This helper element allows extracting color values
+QtObject {
+ property color color;
+
+ function intValue(dec)
+ {
+ var result;
+ switch (dec) {
+ case 'a':
+ result = 10;
+ break;
+ case 'b':
+ result = 11
+ break;
+ case 'c':
+ result = 12;
+ break;
+ case 'd':
+ result = 13;
+ break;
+ case 'e':
+ result = 14
+ case 'f':
+ result = 15
+ break;
+ default:
+ result = dec
+ break;
+ }
+ return Number(result);
+ }
+
+ function convertSubstring(val) {
+ return 16*intValue(val[0]) + intValue(val[1])
+ }
+
+ function grayValue() {
+ return (red + green + blue)/3
+ }
+
+ onColorChanged: {
+ var string = "" + color
+ var redString = string.substring(1, 3)
+ var greenString = string.substring(3,5)
+ var blueString = string.substring(5,7)
+ var alphaString = string.substring(7,9)
+ red = convertSubstring(string.substring(1, 3))
+ green = convertSubstring(string.substring(3,5))
+ blue = convertSubstring(string.substring(5,7))
+ alpha = convertSubstring(string.substring(7,9))
+ }
+
+ property int red
+ property int green
+ property int blue
+ property int alpha
+}
diff --git a/components/custom/visuals/AdjoiningCorner.qml b/components/custom/visuals/AdjoiningCorner.qml
new file mode 100644
index 00000000..92027cef
--- /dev/null
+++ b/components/custom/visuals/AdjoiningCorner.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+
+Item {
+ property string corner: "" // Can we use Qt::Corner? see http://doc.trolltech.com/4.7/qt.html#Corner-enum
+ property alias styledItem: loader.styledItem
+ property alias adjoining: loader.adjoining
+
+ clip: true
+
+ anchors {
+ left: corner == "TopLeftCorner" || corner == "BottomLeftCorner" ? parent.left : parent.horizontalCenter
+ right: corner == "TopLeftCorner" || corner == "BottomLeftCorner" ? parent.horizontalCenter : parent.right
+ top: corner == "TopLeftCorner" || corner == "TopRightCorner" ? parent.top : parent.verticalCenter
+ bottom: corner == "TopLeftCorner" || corner == "TopRightCorner" ? parent.verticalCenter : parent.bottom
+ }
+
+ Item {
+ width: parent.width*2
+ height: parent.height*2
+ x: corner == "TopLeftCorner" || corner == "BottomLeftCorner" ? 0 : -parent.width
+ y: corner == "TopLeftCorner" || corner == "TopRightCorner" ? 0 : -parent.height
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ property Item styledItem:loader.styledItem
+ property int adjoining: 0x0
+ sourceComponent: styling
+ }
+ }
+}
diff --git a/components/custom/visuals/AdjoiningVisual.qml b/components/custom/visuals/AdjoiningVisual.qml
new file mode 100644
index 00000000..09bc34cc
--- /dev/null
+++ b/components/custom/visuals/AdjoiningVisual.qml
@@ -0,0 +1,50 @@
+import QtQuick 1.0
+
+Item {
+ id: adjoiningVisual
+ property int adjoins: 0 // use enum Qt::DockWidgetArea? see http://doc.trolltech.com/4.7/qt.html#DockWidgetArea-enum
+ property Item styledItem
+ property Component styling
+
+// Qt::LeftDockWidgetArea 0x1
+// Qt::RightDockWidgetArea 0x2
+// Qt::TopDockWidgetArea 0x4
+// Qt::BottomDockWidgetArea 0x8
+
+ Item {
+ anchors.fill: parent
+
+ AdjoiningCorner { corner: "TopLeftCorner"; adjoining: topLeftAdjoining(); styledItem: adjoiningVisual.styledItem }
+ AdjoiningCorner { corner: "TopRightCorner"; adjoining: topRightAdjoining(); styledItem: adjoiningVisual.styledItem }
+ AdjoiningCorner { corner: "BottomLeftCorner"; adjoining: bottomLeftAdjoining(); styledItem: adjoiningVisual.styledItem }
+ AdjoiningCorner { corner: "BottomRightCorner"; adjoining: bottomRightAdjoining(); styledItem: adjoiningVisual.styledItem }
+ }
+
+ function topLeftAdjoining() {
+ var adjoining = 0;
+ if(adjoins&0x01) adjoining |= Qt.Horizontal;
+ if(adjoins&0x04) adjoining |= Qt.Vertical;
+ return adjoining;
+ }
+
+ function topRightAdjoining() {
+ var adjoining = 0;
+ if(adjoins&0x02) adjoining |= Qt.Horizontal;
+ if(adjoins&0x04) adjoining |= Qt.Vertical;
+ return adjoining;
+ }
+
+ function bottomLeftAdjoining() {
+ var adjoining = 0;
+ if(adjoins&0x01) adjoining |= Qt.Horizontal;
+ if(adjoins&0x08) adjoining |= Qt.Vertical;
+ return adjoining;
+ }
+
+ function bottomRightAdjoining() {
+ var adjoining = 0;
+ if(adjoins&0x02) adjoining |= Qt.Horizontal;
+ if(adjoins&0x08) adjoining |= Qt.Vertical;
+ return adjoining;
+ }
+}
diff --git a/components/images/folder_new.png b/components/images/folder_new.png
new file mode 100644
index 00000000..8d8bb9bd
--- /dev/null
+++ b/components/images/folder_new.png
Binary files differ
diff --git a/components/plugin/qmldir b/components/plugin/qmldir
new file mode 100644
index 00000000..e8452efd
--- /dev/null
+++ b/components/plugin/qmldir
@@ -0,0 +1 @@
+plugin styleplugin
diff --git a/components/src.pro b/components/src.pro
new file mode 100644
index 00000000..83e0a3d4
--- /dev/null
+++ b/components/src.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = styleitem
diff --git a/components/styleitem/qstyleitem.cpp b/components/styleitem/qstyleitem.cpp
new file mode 100644
index 00000000..90fa5a36
--- /dev/null
+++ b/components/styleitem/qstyleitem.cpp
@@ -0,0 +1,547 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOTgall
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstyleitem.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+#include <QtGui/QApplication>
+#include <QtGui/QMainWindow>
+#include <QtGui/QGroupBox>
+#include <QtGui/QToolBar>
+#include <QtGui/QMenu>
+
+
+QStyleItem::QStyleItem(QObject*parent)
+ : QObject(parent),
+ m_sunken(false),
+ m_raised(false),
+ m_active(true),
+ m_enabled(true),
+ m_selected(false),
+ m_focus(false),
+ m_on(false),
+ m_horizontal(true),
+ m_minimum(0),
+ m_maximum(100),
+ m_value(0)
+{
+}
+
+void QStyleItem::initStyleOption(QStyleOption *opt) const
+{
+ if (m_enabled)
+ opt->state |= QStyle::State_Enabled;
+ if (m_active)
+ opt->state |= QStyle::State_Active;
+ if (m_sunken)
+ opt->state |= QStyle::State_Sunken;
+ if (m_raised)
+ opt->state |= QStyle::State_Raised;
+ if (m_selected)
+ opt->state |= QStyle::State_Selected;
+ if (m_focus)
+ opt->state |= QStyle::State_HasFocus;
+ if (m_on)
+ opt->state |= QStyle::State_On;
+ if (m_hover)
+ opt->state |= QStyle::State_MouseOver;
+ if (m_horizontal)
+ opt->state |= QStyle::State_Horizontal;
+}
+
+QString QStyleBackground::hitTest(int px, int py) const
+{
+ QStyle::SubControl subcontrol = QStyle::SC_All;
+ QStyle::ComplexControl control = QStyle::CC_CustomBase;
+ QString type = m_style->elementType();
+ if (type == QLatin1String("spinbox")) {
+ control = QStyle::CC_SpinBox;
+ QStyleOptionSpinBox opt;
+ opt.rect = QRect(0, 0, width(), height());
+ opt.frame = true;
+ m_style->initStyleOption(&opt);
+ subcontrol = qApp->style()->hitTestComplexControl(control, &opt, QPoint(px,py), 0);
+ if (subcontrol == QStyle::SC_SpinBoxUp)
+ return "up";
+ else if (subcontrol == QStyle::SC_SpinBoxDown)
+ return "down";
+
+ } else if (type == QLatin1String("slider")) {
+ control = QStyle::CC_Slider;
+ QStyleOptionSlider opt;
+ opt.rect = QRect(0, 0, width(), height());
+ opt.minimum = m_style->minimum();
+ opt.maximum = m_style->maximum();
+ opt.sliderPosition = m_style->value();
+ m_style->initStyleOption(&opt);
+ subcontrol = qApp->style()->hitTestComplexControl(control, &opt, QPoint(px,py), 0);
+ if (subcontrol == QStyle::SC_SliderHandle)
+ return "handle";
+ } else if (type == QLatin1String("scrollbar")) {
+ control = QStyle::CC_ScrollBar;
+ QStyleOptionSlider opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ opt.minimum = m_style->minimum();
+ opt.maximum = m_style->maximum();
+ opt.pageStep = 200;
+ opt.orientation = m_style->horizontal() ? Qt::Horizontal : Qt::Vertical;
+ opt.sliderPosition = m_style->value();
+ subcontrol = qApp->style()->hitTestComplexControl(control, &opt, QPoint(px,py), 0);
+
+ if (subcontrol == QStyle::SC_ScrollBarSlider)
+ return "handle";
+ if (subcontrol == QStyle::SC_ScrollBarSubLine || subcontrol == QStyle::SC_ScrollBarSubPage)
+ return "up";
+ if (subcontrol == QStyle::SC_ScrollBarAddLine || subcontrol == QStyle::SC_ScrollBarAddPage)
+ return "down";
+ }
+ return "none";
+}
+
+QSize QStyleItem::sizeFromContents(int width, int height) const
+{
+ QString metric = m_type;
+ if (metric == QLatin1String("checkbox")) {
+ QStyleOptionButton opt;
+ initStyleOption(&opt);
+ opt.text = text();
+ return qApp->style()->sizeFromContents(QStyle::CT_CheckBox, &opt, QSize(width,height), &m_dummywidget);
+ } else if (metric == QLatin1String("button")) {
+ QStyleOptionButton opt;
+ initStyleOption(&opt);
+ opt.text = text();
+ return qApp->style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(width,height), &m_dummywidget);
+ } else if (metric == QLatin1String("tab")) {
+ QStyleOptionTabV3 opt;
+ initStyleOption(&opt);
+ opt.text = text();
+ return qApp->style()->sizeFromContents(QStyle::CT_TabBarTab, &opt, QSize(width,height), &m_dummywidget);
+ } else if (metric == QLatin1String("combobox")) {
+ QStyleOptionComboBox opt;
+ initStyleOption(&opt);
+ return qApp->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, QSize(width,height), &m_dummywidget);
+ } else if (metric == QLatin1String("spinbox")) {
+
+ QStyleOptionSpinBox opt;
+ initStyleOption(&opt);
+ return qApp->style()->sizeFromContents(QStyle::CT_SpinBox, &opt, QSize(width,height), &m_dummywidget);
+ } else if (metric == QLatin1String("edit")) {
+ QStyleOptionFrameV3 opt;
+ initStyleOption(&opt);
+ return qApp->style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(width,height), &m_dummywidget);
+ }
+ return QSize();
+}
+
+int QStyleItem::pixelMetric(const QString &metric) const
+{
+ if (metric == "scrollbarExtent")
+ return qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+ else if (metric == "defaultframewidth")
+ return qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ else if (metric == "taboverlap")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarTabOverlap);
+ else if (metric == "tabbaseoverlap")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarBaseOverlap);
+ else if (metric == "tabbaseheight")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarBaseHeight);
+ else if (metric == "tabvshift")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarTabShiftVertical);
+ else if (metric == "menuhmargin")
+ return qApp->style()->pixelMetric(QStyle::PM_MenuHMargin);
+ else if (metric == "menuvmargin")
+ return qApp->style()->pixelMetric(QStyle::PM_MenuVMargin);
+ else if (metric == "menupanelwidth")
+ return qApp->style()->pixelMetric(QStyle::PM_MenuPanelWidth);
+ return 0;
+}
+
+QVariant QStyleItem::styleHint(const QString &metric) const
+{
+ if (metric == "focuswidget")
+ return qApp->style()->styleHint(QStyle::SH_FocusFrame_AboveWidget);
+ if (metric == "tabbaralignment") {
+ int result = qApp->style()->styleHint(QStyle::SH_TabBar_Alignment);
+ if (result == Qt::AlignCenter)
+ return "center";
+ return "left";
+ }
+ if (metric == "framearoundcontents")
+ return qApp->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents);
+ return 0;
+}
+
+
+QRect QStyleBackground::subControlRect(const QString &subcontrolString) const
+{
+ QStyle::SubControl subcontrol = QStyle::SC_None;
+ QString m_type = m_style->elementType();
+ if (m_type == QLatin1String("spinbox")) {
+ QStyle::ComplexControl control = QStyle::CC_SpinBox;
+ QStyleOptionSpinBox opt;
+ m_style->initStyleOption(&opt);
+ opt.rect = QRect(0, 0, width(), height());
+ opt.frame = true;
+ if (subcontrolString == QLatin1String("down"))
+ subcontrol = QStyle::SC_SpinBoxDown;
+ else if (subcontrolString == QLatin1String("up"))
+ subcontrol = QStyle::SC_SpinBoxUp;
+ else if (subcontrolString == QLatin1String("edit")){
+ subcontrol = QStyle::SC_SpinBoxEditField;
+ }
+ return qApp->style()->subControlRect(control, &opt, subcontrol, 0);
+ } else if (m_type == QLatin1String("slider")) {
+ QStyle::ComplexControl control = QStyle::CC_Slider;
+ QStyleOptionSlider opt;
+ m_style->initStyleOption(&opt);
+ opt.rect = QRect(0, 0, width(), height());
+ opt.minimum = m_style->minimum();
+ opt.maximum = m_style->maximum();
+ opt.sliderPosition = m_style->value();
+ if (subcontrolString == QLatin1String("handle"))
+ subcontrol = QStyle::SC_SliderHandle;
+ else if (subcontrolString == QLatin1String("groove"))
+ subcontrol = QStyle::SC_SliderGroove;
+ return qApp->style()->subControlRect(control, &opt, subcontrol, 0);
+ } else if (m_type == QLatin1String("scrollbar")) {
+ QStyle::ComplexControl control = QStyle::CC_ScrollBar;
+ QStyleOptionSlider opt;
+ m_style->initStyleOption(&opt);
+ opt.rect = QRect(0, 0, width(), height());
+ opt.minimum = m_style->minimum();
+ opt.maximum = m_style->maximum();
+ opt.pageStep = m_style->horizontal() ? width() : height();
+ opt.orientation = m_style->horizontal() ? Qt::Horizontal : Qt::Vertical;
+ opt.sliderPosition = m_style->value();
+ if (subcontrolString == QLatin1String("slider"))
+ subcontrol = QStyle::SC_ScrollBarSlider;
+ if (subcontrolString == QLatin1String("groove"))
+ subcontrol = QStyle::SC_ScrollBarGroove;
+ else if (subcontrolString == QLatin1String("handle"))
+ subcontrol = QStyle::SC_ScrollBarSlider;
+ else if (subcontrolString == QLatin1String("add"))
+ subcontrol = QStyle::SC_ScrollBarAddPage;
+ else if (subcontrolString == QLatin1String("sub"))
+ subcontrol = QStyle::SC_ScrollBarSubPage;
+ return qApp->style()->subControlRect(control, &opt, subcontrol, 0);
+ }
+ return QRect();
+}
+
+QStyleBackground::QStyleBackground(QDeclarativeItem *parent)
+ : QDeclarativeItem(parent),
+ m_menu(0),
+ m_style(0)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+ setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ setSmooth(true);
+
+ m_menu = new QMenu();
+ m_menu->ensurePolished();
+}
+
+void QStyleBackground::setStyle(QStyleItem *style)
+{
+ if (m_style != style) {
+ m_style = style;
+ //connect(&m_dummywidget, SIGNAL(updateRequest()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(onChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(selectedChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(activeChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(textChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(activeChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(raisedChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(sunkenChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(hoverChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(maximumChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(minimumChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(valueChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(enabledChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(horizontalChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(activeControlChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(focusChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(activeControlChanged()), this, SLOT(updateItem()));
+ connect(m_style, SIGNAL(elementTypeChanged()), this, SLOT(updateItem()));
+ emit styleChanged();
+ }
+}
+
+
+void QStyleBackground::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ QString type = m_style->elementType();
+ if (type == QLatin1String("button")) {
+ QStyle::ControlElement control = QStyle::CE_PushButton;
+ QStyleOptionButton opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+
+ // Dirty hack to fix button label positioning on mac
+ if (qApp->style()->metaObject()->className() == QLatin1String("QMacStyle"))
+ opt.rect.translate(0,2);
+
+ qApp->style()->drawControl(control, &opt, painter, &m_dummywidget);
+ }
+ else if (type == QLatin1String("toolbutton")) {
+ QStyle::ComplexControl control = QStyle::CC_ToolButton;
+ QStyleOptionToolButton opt;
+ m_style->initStyleOption(&opt);
+ opt.subControls = QStyle::SC_ToolButton;
+ opt.rect = QRect(0, 0, width(), height());
+ QToolBar bar;
+ QWidget dummy(&bar);
+ if (opt.state & QStyle::State_Raised || opt.state & QStyle::State_On)
+ qApp->style()->drawComplexControl(control, &opt, painter, &dummy);
+ }
+ else if (type == QLatin1String("tab")) {
+ QStyle::ControlElement control = QStyle::CE_TabBarTabShape;
+ QStyleOptionTabV3 opt;
+ m_style->initStyleOption(&opt);
+ int overlap = qApp->style()->pixelMetric(QStyle::PM_TabBarTabOverlap);
+ opt.rect = QRect(overlap, 0, width()-2*overlap, height());
+ if (m_style->text() == "South")
+ opt.shape = QTabBar::RoundedSouth;
+ if (m_style->activeControl() == QLatin1String("beginning"))
+ opt.position = QStyleOptionTabV3::Beginning;
+ else if (m_style->activeControl() == QLatin1String("end"))
+ opt.position = QStyleOptionTabV3::End;
+ else if (m_style->activeControl() == QLatin1String("only"))
+ opt.position = QStyleOptionTabV3::OnlyOneTab;
+ else
+ opt.position = QStyleOptionTabV3::Middle;
+ qApp->style()->drawControl(control, &opt, painter, &m_dummywidget);
+ }
+ else if (type == QLatin1String("menu")) {
+ QStyleOptionMenuItem opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ QStyleHintReturnMask val;
+ qApp->style()->styleHint(QStyle::SH_Menu_Mask, &opt, &m_dummywidget, &val);
+ painter->save();
+ painter->setClipRegion(val.region);
+ m_menu->setContextMenuPolicy(Qt::CustomContextMenu);
+ m_menu->ensurePolished();
+ opt.palette = m_menu->palette();
+ painter->fillRect(opt.rect, opt.palette.window());
+ painter->restore();
+ qApp->style()->drawPrimitive(QStyle::PE_PanelMenu, &opt, painter, m_menu);
+ QStyleOptionFrame frame;
+ m_style->initStyleOption(&frame);
+ frame.lineWidth = qApp->style()->pixelMetric(QStyle::PM_MenuPanelWidth);
+ frame.midLineWidth = 0;
+ frame.rect = opt.rect;
+ qApp->style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, painter, m_menu);
+ // qApp->style()->drawControl(QStyle::CE_MenuVMargin, &opt, painter, m_menu);
+ }
+ else if (type == QLatin1String("frame")) {
+ QStyle::PrimitiveElement control = QStyle::PE_Frame;
+ QStyleOptionFrameV3 opt;
+ opt.rect = QRect(0, 0, width(), height());
+ opt.frameShape = QFrame::StyledPanel;
+ opt.lineWidth = 1;
+ m_style->initStyleOption(&opt);
+ qApp->style()->drawPrimitive(control, &opt, painter, 0);
+ }
+ else if (type == QLatin1String("focusframe")) {
+ QStyle::ControlElement control = QStyle::CE_FocusFrame;
+ QStyleOption opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ qApp->style()->drawControl(control, &opt, painter, &m_dummywidget);
+ }
+ else if (type == QLatin1String("tabframe")) {
+ QStyle::PrimitiveElement control = QStyle::PE_FrameTabWidget;
+ if (m_style->minimum()) {
+ QStyleOptionTabWidgetFrameV2 opt;
+ m_style->initStyleOption(&opt);
+ if (m_style->text() == "South")
+ opt.shape = QTabBar::RoundedSouth;
+ opt.selectedTabRect = QRect(m_style->value(), 0, m_style->minimum(), height());
+ opt.rect = QRect(0, 0, width(), height());
+ qApp->style()->drawPrimitive(control, &opt, painter, 0);
+ } else {
+ QStyleOptionTabWidgetFrame opt;
+ m_style->initStyleOption(&opt);
+ opt.rect = QRect(0, 0, width(), height());
+ qApp->style()->drawPrimitive(control, &opt, painter, 0);
+ }
+ }
+ else if (type == QLatin1String("menuitem")) {
+ QStyle::ControlElement control = QStyle::CE_MenuItem;
+ QStyleOptionMenuItem opt;
+ opt.rect = QRect(0, 0, width(), height());
+ opt.text = m_style->text();
+ m_style->initStyleOption(&opt);
+ opt.palette = m_menu->palette();
+ qApp->style()->drawControl(control, &opt, painter, m_menu);
+ }
+ else if (type == QLatin1String("checkbox")) {
+ QStyle::ControlElement control = QStyle::CE_CheckBox;
+ QStyleOptionButton opt;
+ m_style->initStyleOption(&opt);
+ if (!(opt.state & QStyle::State_On))
+ opt.state |= QStyle::State_Off;
+ opt.rect = QRect(0, 0, width(), height());
+ opt.text = m_style->text();
+ qApp->style()->drawControl(control, &opt, painter, 0);
+ }
+ else if (type == QLatin1String("radiobutton")) {
+ QStyle::ControlElement control = QStyle::CE_RadioButton;
+ QStyleOptionButton opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ opt.text = m_style->text();
+ qApp->style()->drawControl(control, &opt, painter, 0);
+ }
+ else if (type == QLatin1String("edit")) {
+ QStyle::PrimitiveElement control = QStyle::PE_PanelLineEdit;
+ QStyleOptionFrameV3 opt;
+ opt.rect = QRect(0, 0, width(), height());
+ opt.lineWidth = 1; // jens : this must be non-zero
+ m_style->initStyleOption(&opt);
+ qApp->style()->drawPrimitive(control, &opt, painter, 0);
+ }
+ else if (type == QLatin1String("slidergroove")) {
+ QStyle::ComplexControl control = QStyle::CC_Slider;
+ QStyleOptionSlider opt;
+ opt.rect = QRect(0, 0, width(), height());
+ opt.minimum = 0;
+ opt.maximum = 100;
+ opt.subControls |= (QStyle::SC_SliderGroove);
+ opt.activeSubControls = QStyle::SC_SliderHandle;
+ m_style->initStyleOption(&opt);
+ qApp->style()->drawComplexControl(control, &opt, painter, 0);
+ }
+ else if (type == QLatin1String("combobox")) {
+ QStyle::ComplexControl control = QStyle::CC_ComboBox;
+ QStyleOptionComboBox opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ m_dummywidget.activateWindow();
+ qApp->style()->drawComplexControl(control, &opt, painter, &m_dummywidget);
+ }
+ else if (type == QLatin1String("spinbox")) {
+ QStyle::ComplexControl control = QStyle::CC_SpinBox;
+ QStyleOptionSpinBox opt;
+ opt.rect = QRect(0, 0, width(), height());
+ opt.frame = true;
+ m_style->initStyleOption(&opt);
+ if (m_style->value() & 0x1)
+ opt.activeSubControls = QStyle::SC_SpinBoxUp;
+ else if (m_style->value() & (1<<1))
+ opt.activeSubControls = QStyle::SC_SpinBoxDown;
+ opt.subControls |= QStyle::SC_SpinBoxDown;
+ opt.subControls |= QStyle::SC_SpinBoxUp;
+ if (m_style->value() & (1<<2))
+ opt.stepEnabled |= QAbstractSpinBox::StepUpEnabled;
+ if (m_style->value() & (1<<3))
+ opt.stepEnabled |= QAbstractSpinBox::StepDownEnabled;
+ qApp->style()->drawComplexControl(control, &opt, painter, 0);
+ }
+ else if (type == QLatin1String("slider")) {
+ QStyle::ComplexControl control = QStyle::CC_Slider;
+ QStyleOptionSlider opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ opt.minimum = m_style->minimum();
+ opt.maximum = m_style->maximum();
+ opt.tickPosition = QSlider::TicksBelow;
+ opt.sliderPosition = m_style->value();
+ opt.tickInterval = 1200 / (opt.maximum - opt.minimum);
+ opt.sliderValue = m_style->value();
+ opt.subControls = QStyle::SC_SliderTickmarks | QStyle::SC_SliderGroove | QStyle::SC_SliderHandle;
+ opt.activeSubControls = QStyle::SC_None;
+ qApp->style()->drawComplexControl(control, &opt, painter, 0);
+ }
+ else if (type == QLatin1String("progressbar")) {
+ QStyle::ControlElement control = QStyle::CE_ProgressBar;
+ QStyleOptionProgressBarV2 opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ opt.minimum = m_style->minimum();
+ opt.maximum = m_style->maximum();
+ opt.progress = m_style->value();
+ qApp->style()->drawControl(control, &opt, painter, &m_dummywidget);
+ }
+ else if (type == QLatin1String("toolbar")) {
+ QStyle::ControlElement control = QStyle::CE_ToolBar;
+ QStyleOptionToolBar opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ QMainWindow mw;
+ QWidget w(&mw);
+ qApp->style()->drawControl(control, &opt, painter, &w);
+ }
+ else if (type == QLatin1String("groupbox")) {
+ QStyle::ComplexControl control = QStyle::CC_GroupBox;
+ QStyleOptionGroupBox opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ opt.text = m_style->text();
+ opt.lineWidth = 1;
+ opt.subControls = QStyle::SC_GroupBoxLabel;
+ // oxygen crashes if we dont pass a widget
+ qApp->style()->drawComplexControl(control, &opt, painter, &m_dummywidget);
+ }
+ else if (type == QLatin1String("scrollbar")) {
+ QStyle::ComplexControl control = QStyle::CC_ScrollBar;
+ QStyleOptionSlider opt;
+ opt.rect = QRect(0, 0, width(), height());
+ m_style->initStyleOption(&opt);
+ opt.minimum = m_style->minimum();
+ opt.maximum = m_style->maximum();
+ opt.pageStep = m_style->horizontal() ? width() : height();
+ opt.orientation = m_style->horizontal() ? Qt::Horizontal : Qt::Vertical;
+ opt.sliderPosition = m_style->value();
+ opt.sliderValue = m_style->value();
+ opt.activeSubControls = (m_style->activeControl() == QLatin1String("up"))
+ ? QStyle::SC_ScrollBarSubLine :
+ (m_style->activeControl() == QLatin1String("down")) ?
+ QStyle::SC_ScrollBarAddLine:
+ QStyle::SC_ScrollBarSlider;
+
+ opt.sliderValue = m_style->value();
+ opt.subControls = QStyle::SC_All;
+ qApp->style()->drawComplexControl(control, &opt, painter, &m_dummywidget);
+ }
+}
diff --git a/components/styleitem/qstyleitem.h b/components/styleitem/qstyleitem.h
new file mode 100644
index 00000000..5d195252
--- /dev/null
+++ b/components/styleitem/qstyleitem.h
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef STYLEWRAPPER_H
+#define STYLEWRAPPER_H
+
+#include <QDeclarativeItem>
+#include <QtGui/QStyle>
+#include <QtGui>
+#include <QEvent>
+
+/**
+ * This class adds experimental support for
+ * animated progressbars
+ */
+class AnimWidget: public QProgressBar
+{
+Q_OBJECT
+public:
+ AnimWidget(QWidget *parent = 0):
+ QProgressBar(parent) {
+ setMaximum(100);
+ setMinimum(0);
+ setValue(50);
+ // setAttribute(Qt::WA_WState_InPaintEvent);
+ // setAttribute(Qt::WA_WState_Visible, true);
+ }
+public:
+ bool event(QEvent *e){
+ // emit updateRequest();
+ return QProgressBar::event(e);
+ }
+signals:
+ void updateRequest();
+};
+
+class QStyleItem: public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY( bool sunken READ sunken WRITE setSunken NOTIFY sunkenChanged)
+ Q_PROPERTY( bool raised READ raised WRITE setRaised NOTIFY raisedChanged)
+ Q_PROPERTY( bool active READ active WRITE setActive NOTIFY activeChanged)
+ Q_PROPERTY( bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY( bool selected READ selected WRITE setSelected NOTIFY selectedChanged)
+ Q_PROPERTY( bool focus READ focus WRITE setFocus NOTIFY focusChanged)
+ Q_PROPERTY( bool on READ on WRITE setOn NOTIFY onChanged)
+ Q_PROPERTY( bool hover READ hover WRITE setHover NOTIFY hoverChanged)
+ Q_PROPERTY( bool horizontal READ horizontal WRITE setHorizontal NOTIFY horizontalChanged)
+ Q_PROPERTY( QString elementType READ elementType WRITE setElementType NOTIFY elementTypeChanged)
+ Q_PROPERTY( QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY( QString activeControl READ activeControl WRITE setActiveControl NOTIFY activeControlChanged)
+
+ // For range controls
+ Q_PROPERTY( int minimum READ minimum WRITE setMinimum NOTIFY minimumChanged)
+ Q_PROPERTY( int maximum READ maximum WRITE setMaximum NOTIFY maximumChanged)
+ Q_PROPERTY( int value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ QStyleItem(QObject *parent = 0);
+
+ bool sunken() const { return m_sunken; }
+ bool raised() const { return m_raised; }
+ bool active() const { return m_active; }
+ bool enabled() const { return m_enabled; }
+ bool selected() const { return m_selected; }
+ bool focus() const { return m_focus; }
+ bool on() const { return m_on; }
+ bool hover() const { return m_hover; }
+ bool horizontal() const { return m_horizontal; }
+ int minimum() const { return m_minimum; }
+ int maximum() const { return m_maximum; }
+ int value() const { return m_value; }
+ QString elementType() const { return m_type; }
+ QString text() const { return m_text; }
+ QString activeControl() const { return m_activeControl; }
+
+ void setSunken(bool sunken) { if (m_sunken != sunken) {m_sunken = sunken; emit sunkenChanged();}}
+ void setRaised(bool raised) { if (m_raised!= raised) {m_raised = raised; emit raisedChanged();}}
+ void setActive(bool active) { if (m_active!= active) {m_active = active; emit activeChanged();}}
+ void setEnabled(bool enabled) { if (m_enabled!= enabled) {m_enabled = enabled; emit enabledChanged();}}
+ void setSelected(bool selected) { if (m_selected!= selected) {m_selected = selected; emit selectedChanged();}}
+ void setFocus(bool focus) { if (m_focus != focus) {m_focus = focus; emit focusChanged();}}
+ void setOn(bool on) { if (m_on != on) {m_on = on ; emit onChanged();}}
+ void setHover(bool hover) { if (m_hover != hover) {m_hover = hover ; emit hoverChanged();}}
+ void setHorizontal(bool horizontal) { if (m_horizontal != horizontal) {m_horizontal = horizontal; emit horizontalChanged();}}
+ void setMinimum(int minimum) { if (m_minimum!= minimum) {m_minimum = minimum; emit minimumChanged();}}
+ void setMaximum(int maximum) { if (m_maximum != maximum) {m_maximum = maximum; emit maximumChanged();}}
+ void setValue(int value) { if (m_value!= value) {m_value = value; emit valueChanged();}}
+ void setElementType(const QString &str) { if (m_type != str) {m_type = str; emit elementTypeChanged();}}
+ void setText(const QString &str) { if (m_text != str) {m_text = str; emit textChanged();}}
+ void setActiveControl(const QString &str) { if (m_activeControl != str) {m_activeControl = str; emit activeControlChanged();}}
+
+ virtual void initStyleOption(QStyleOption *opt) const;
+public Q_SLOTS:
+ int pixelMetric(const QString&) const;
+ QVariant styleHint(const QString&) const;
+ QSize sizeFromContents(int width, int height) const;
+
+Q_SIGNALS:
+ void elementTypeChanged();
+ void textChanged();
+ void sunkenChanged();
+ void raisedChanged();
+ void activeChanged();
+ void enabledChanged();
+ void selectedChanged();
+ void focusChanged();
+ void onChanged();
+ void hoverChanged();
+ void horizontalChanged();
+ void minimumChanged();
+ void maximumChanged();
+ void valueChanged();
+ void activeControlChanged();
+
+protected:
+ QString m_type;
+ QString m_text;
+ QString m_activeControl;
+ bool m_sunken;
+ bool m_raised;
+ bool m_active;
+ bool m_enabled;
+ bool m_selected;
+ bool m_focus;
+ bool m_hover;
+ bool m_on;
+ bool m_horizontal;
+ int m_minimum;
+ int m_maximum;
+ int m_value;
+ AnimWidget m_dummywidget;
+};
+
+class QStyleBackground: public QDeclarativeItem
+{
+ Q_OBJECT
+public:
+ Q_PROPERTY( QStyleItem* style READ style WRITE setStyle NOTIFY styleChanged)
+
+ QStyleBackground(QDeclarativeItem *parent = 0);
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+public Q_SLOTS:
+ QStyleItem *style(){return m_style;}
+ void setStyle(QStyleItem *style);
+ void updateItem(){update();}
+ QString hitTest(int x, int y) const;
+ QRect subControlRect(const QString &subcontrolString) const;
+
+Q_SIGNALS:
+ void styleChanged();
+
+private:
+ AnimWidget m_dummywidget;
+ QWidget *m_menu;
+ QStyleItem *m_style;
+};
+
+#endif //STYLEWRAPPER_H
diff --git a/components/styleitem/qstyleplugin.cpp b/components/styleitem/qstyleplugin.cpp
new file mode 100644
index 00000000..05cb45c5
--- /dev/null
+++ b/components/styleitem/qstyleplugin.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qdeclarative.h>
+#include "qstyleplugin.h"
+#include "qstyleitem.h"
+
+#include <qdeclarativeextensionplugin.h>
+
+#include <qdeclarativeengine.h>
+#include <qdeclarative.h>
+#include <qdeclarativeitem.h>
+#include <qdeclarativeimageprovider.h>
+#include <qdeclarativeview.h>
+#include <QApplication>
+#include <QImage>
+
+// Load icons from desktop theme
+class DesktopIconProvider : public QDeclarativeImageProvider
+{
+public:
+ DesktopIconProvider()
+ : QDeclarativeImageProvider(QDeclarativeImageProvider::Pixmap)
+ {
+ }
+
+ QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
+ {
+ int pos = id.lastIndexOf('/');
+ QString iconName = id.right(id.length() - pos);
+ int width = qApp->style()->pixelMetric(QStyle::PM_ToolBarIconSize);
+ return QIcon::fromTheme(iconName).pixmap(width);
+ }
+};
+
+void StylePlugin::registerTypes(const char *uri)
+{
+ qmlRegisterType<QStyleItem>(uri, 1, 0, "QStyleItem");
+ qmlRegisterType<QStyleBackground>(uri, 1, 0, "QStyleBackground");
+}
+
+void StylePlugin::initializeEngine(QDeclarativeEngine *engine, const char *uri)
+{
+ engine->addImageProvider("desktoptheme", new DesktopIconProvider);
+}
+
+Q_EXPORT_PLUGIN2(styleplugin, StylePlugin);
diff --git a/components/styleitem/qstyleplugin.h b/components/styleitem/qstyleplugin.h
new file mode 100644
index 00000000..45aff70f
--- /dev/null
+++ b/components/styleitem/qstyleplugin.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef STYLEPLUGIN_H
+#define STYLEPLUGIN_H
+
+#include <QDeclarativeExtensionPlugin>
+#include <QtScript/QScriptValue>
+#include <QtCore/QTimer>
+
+class StylePlugin : public QDeclarativeExtensionPlugin
+{
+ Q_OBJECT
+public:
+ void registerTypes(const char *uri);
+ void initializeEngine(QDeclarativeEngine *engine, const char *uri);
+};
+
+#endif // STYLEPLUGIN_H
diff --git a/components/styleitem/styleitem.pro b/components/styleitem/styleitem.pro
new file mode 100644
index 00000000..b254cd1e
--- /dev/null
+++ b/components/styleitem/styleitem.pro
@@ -0,0 +1,38 @@
+TEMPLATE = lib
+CONFIG += qt plugin
+QT += declarative
+QT += script
+
+TARGET = styleplugin
+
+DESTDIR = ..\\plugin
+OBJECTS_DIR = tmp
+MOC_DIR = tmp
+
+HEADERS += qstyleplugin.h \
+ qstyleitem.h
+
+SOURCES += qstyleplugin.cpp \
+ qstyleitem.cpp
+
+
+OTHER_FILES += \
+ ../widgets/Button.qml \
+ ../widgets/CheckBox.qml \
+ ../widgets/ChoiceList.qml \
+ ../widgets/GroupBox.qml \
+ ../widgets/ProgressBar.qml \
+ ../widgets/RadioButton.qml \
+ ../widgets/ScrollArea.qml \
+ ../widgets/ScrollBar.qml \
+ ../widgets/Slider.qml \
+ ../widgets/SpinBox.qml \
+ ../widgets/Switch.qml \
+ ../widgets/TextArea.qml \
+ ../widgets/TextField.qml \
+ ../widgets/ToolBar.qml \
+ ../widgets/ToolButton.qml \
+ ../gallery.qml \
+ ../widgets/Tab.qml \
+ ../widgets/TabBar.qml \
+ ../widgets/TabFrame.qml
diff --git a/src/Button.qml b/src/Button.qml
new file mode 100644
index 00000000..496d37df
--- /dev/null
+++ b/src/Button.qml
@@ -0,0 +1,27 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Button {
+ id:button
+
+ property int buttonHeight: Math.max(22, styleitem.sizeFromContents(100, 6).height)
+ height: buttonHeight
+
+ QStyleItem {
+ id:styleitem
+ elementType:"button"
+ sunken: pressed
+ raised: !pressed
+ hover: containsMouse
+ enabled:button.enabled
+ text:button.text
+ }
+
+ background:
+ QStyleBackground {
+ style:styleitem
+ anchors.fill:parent
+ }
+}
+
diff --git a/src/ButtonRow.qml b/src/ButtonRow.qml
new file mode 100644
index 00000000..623c5f44
--- /dev/null
+++ b/src/ButtonRow.qml
@@ -0,0 +1,5 @@
+import QtQuick 1.0
+import "../../../components" as Components
+
+Components.ButtonRow {
+}
diff --git a/src/CheckBox.qml b/src/CheckBox.qml
new file mode 100644
index 00000000..632dce2d
--- /dev/null
+++ b/src/CheckBox.qml
@@ -0,0 +1,26 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jb : Size should not depend on background, we should make it consistent
+
+Components.CheckBox{
+ id:checkbox
+ property variant text
+ width:100
+ height:18
+
+ background: QStyleBackground {
+ id:styleitem
+ style:QStyleItem {
+ elementType:"checkbox"
+ sunken:pressed
+ on:checked || pressed
+ hover:containsMouse
+ text:checkbox.text
+ enabled:checkbox.enabled
+ }
+ }
+ checkmark: null
+}
+
diff --git a/src/ChoiceList.qml b/src/ChoiceList.qml
new file mode 100644
index 00000000..5015fbef
--- /dev/null
+++ b/src/ChoiceList.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.ChoiceList {
+ id:choicelist
+
+ property int buttonHeight: buttonitem.sizeFromContents(100, 18).height
+ QStyleItem { id:buttonitem; elementType:"combobox" }
+ height: buttonHeight
+ topMargin:4
+ bottomMargin:4
+
+ QStyleItem {
+ id:styleitem
+ elementType: "combobox"
+ sunken: pressed
+ raised: !pressed
+ hover: containsMouse
+ enabled:choicelist.enabled
+ }
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: styleitem
+ }
+
+ listItem: Item {
+ id:item
+
+ height:22
+ anchors.left:parent.left
+ width:choicelist.width
+ QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType: "menuitem"
+ text: choicelist.model.get(index).text
+ selected: highlighted
+ }
+ }
+ }
+
+ popupFrame: QStyleBackground {
+ property int fw: styleitem.pixelMetric("menupanelwidth");
+ anchors.leftMargin: styleitem.pixelMetric("menuhmargin") + fw
+ anchors.rightMargin: styleitem.pixelMetric("menuhmargin") + fw
+ anchors.topMargin: styleitem.pixelMetric("menuvmargin") + fw
+ anchors.bottomMargin: styleitem.pixelMetric("menuvmargin") + fw
+ style:QStyleItem{elementType:"menu"}
+ }
+}
diff --git a/src/GroupBox.qml b/src/GroupBox.qml
new file mode 100644
index 00000000..0d45810d
--- /dev/null
+++ b/src/GroupBox.qml
@@ -0,0 +1,27 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Item {
+ width:200
+ height:46
+
+ property alias text: styleitem.text
+ default property alias children: content.children
+ property bool checkable: false
+
+ QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ id:styleitem
+ elementType:"groupbox"
+ }
+
+ Item {
+ id:content
+ anchors.topMargin:22
+ anchors.leftMargin:6
+ anchors.fill:parent
+ }
+ }
+}
diff --git a/src/ProgressBar.qml b/src/ProgressBar.qml
new file mode 100644
index 00000000..bf29bcac
--- /dev/null
+++ b/src/ProgressBar.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.ProgressBar {
+ id:progressbar
+
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 15).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ height: buttonHeight
+
+ background: QStyleBackground{
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType:"progressbar"
+
+ // XXX: since desktop uses int instead of real, the progressbar
+ // range [0..1] must be stretched to a good precision
+ property int factor : 1000000
+
+ value: progressbar.value * factor
+ minimum: indeterminate ? 0 : progressbar.minimumValue * factor
+ maximum: indeterminate ? 0 : progressbar.maximumValue * factor
+ enabled: progressbar.enabled
+ }
+ }
+ indeterminateProgress:null
+ progress: null
+}
+
diff --git a/src/RadioButton.qml b/src/RadioButton.qml
new file mode 100644
index 00000000..3c2c3e54
--- /dev/null
+++ b/src/RadioButton.qml
@@ -0,0 +1,26 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jb : Size should not depend on background, we should make it consistent
+
+Components.RadioButton{
+ id:radiobutton
+ property variant text
+ width:110
+ height:18
+
+ background: QStyleBackground {
+
+ style: QStyleItem{
+ elementType:"radiobutton"
+ sunken:pressed
+ on:checked || pressed
+ hover:containsMouse
+ text:radiobutton.text
+ enabled:radiobutton.enabled
+ }
+ }
+ checkmark: null
+}
+
diff --git a/src/ScrollArea.qml b/src/ScrollArea.qml
new file mode 100644
index 00000000..3a904dde
--- /dev/null
+++ b/src/ScrollArea.qml
@@ -0,0 +1,103 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+FocusScope {
+ id:scrollarea
+ width: 100
+ height: 100
+
+ property int contentMargin: 1
+ property int __scrollbarExtent : styleitem.pixelMetric("scrollbarExtent");
+ property int frameWidth: styleitem.pixelMetric("defaultframewidth");
+ property int contentHeight : content.childrenRect.height
+ property int contentWidth: content.childrenRect.width
+ property alias color: flickable.color
+ property bool frame: true
+ property bool highlightOnFocus: false
+
+ default property alias children: content.children
+
+ property int contentY
+ property int contentX
+
+ property bool frameAroundContents: styleitem.styleHint("framearoundcontents")
+
+ onContentYChanged: {
+ vscrollbar.value = contentY
+ }
+
+ onContentXChanged: {
+ hscrollbar.value = contentX
+ }
+
+ QStyleBackground {
+ style: QStyleItem{
+ id:styleitem
+ elementType: frame ? "frame" : ""
+ sunken: true
+ }
+ anchors.fill: parent
+ anchors.rightMargin: (frameAroundContents && vscrollbar.visible) ? vscrollbar.width + 4 : -frameWidth
+ anchors.bottomMargin: (frameAroundContents && hscrollbar.visible) ? hscrollbar.height + 4 : -frameWidth
+ anchors.topMargin: (frameAroundContents && hscrollbar.visible) ? hscrollbar.height + 4 : -frameWidth
+
+ Rectangle {
+ id:flickable
+ color: "transparent"
+ anchors.fill: parent
+ anchors.margins: frame ? 2 : 0
+ clip: true
+
+ Item {
+ id: docmargins
+ anchors.fill:parent
+ anchors.margins:contentMargin
+ Item {
+ id: content
+ x: -scrollarea.contentX
+ y: -scrollarea.contentY
+ }
+ }
+ }
+ }
+
+ ScrollBar {
+ id: hscrollbar
+ orientation: Qt.Horizontal
+ visible: contentWidth > flickable.width
+ maximumValue: contentWidth > flickable.width ? scrollarea.contentWidth - flickable.width : 0
+ minimumValue: 0
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: { return (frame ? 1 : 0) + ( vscrollbar.visible ? __scrollbarExtent : 0) }
+ onValueChanged: contentX = value
+ }
+
+ ScrollBar {
+ id: vscrollbar
+ orientation: Qt.Vertical
+ visible: contentHeight > flickable.height
+ maximumValue: contentHeight > flickable.height ? scrollarea.contentHeight - flickable.height : 0
+ minimumValue: 0
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: { return (frame ? 1 : 0) + (hscrollbar.visible ? __scrollbarExtent : 0) }
+ onValueChanged: contentY = value
+ }
+
+ QStyleBackground {
+ z:2
+ anchors.fill:parent
+ anchors.margins:-2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ visible: highlightOnFocus && parent.activeFocus && styleitem.styleHint("focuswidget")
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+}
diff --git a/src/ScrollBar.qml b/src/ScrollBar.qml
new file mode 100644
index 00000000..ea822b62
--- /dev/null
+++ b/src/ScrollBar.qml
@@ -0,0 +1,109 @@
+import QtQuick 1.1
+import "../../../components" as Components
+import "../plugin"
+
+MouseArea {
+ id:scrollbar
+ property int __scrollbarExtent : styleitem.pixelMetric("scrollbarExtent");
+ implicitWidth:orientation == Qt.Horizontal ? 200 : __scrollbarExtent;
+ implicitHeight:orientation == Qt.Horizontal ? __scrollbarExtent : 200
+
+ property int orientation : Qt.Horizontal
+ property alias minimumValue: slider.minimumValue
+ property alias maximumValue: slider.maximumValue
+ property alias value: slider.value
+
+ property bool upPressed;
+ property bool downPressed;
+ property bool __autoincrement: false
+
+ // Update hover item
+ onEntered: styleitem.activeControl = bgitem.hitTest(mouseX, mouseY)
+ onExited: styleitem.activeControl = "none"
+ onMouseXChanged: styleitem.activeControl = bgitem.hitTest(mouseX, mouseY)
+ hoverEnabled:true
+
+ Timer { running: upPressed || downPressed; interval: 350 ; onTriggered: __autoincrement = true }
+ Timer { running: __autoincrement; interval: 60 ; repeat: true ;
+ onTriggered: upPressed ? decrement() : increment() }
+
+ onPressed: {
+ var control = bgitem.hitTest(mouseX,mouseY)
+ if (control == "up") {
+ upPressed = true
+ } else if (control == "down") {
+ downPressed = true
+ }
+ }
+
+ onReleased: {
+ __autoincrement = false;
+ if (upPressed) {
+ upPressed = false;
+ decrement()
+ } else if (downPressed) {
+ increment()
+ downPressed = false;
+ }
+ }
+
+ function increment() {
+ value += 30
+ if (value > maximumValue)
+ value = maximumValue
+ }
+
+ function decrement() {
+ value -= 30
+ if (value < minimumValue)
+ value = minimumValue
+ }
+
+ QStyleBackground {
+ id:bgitem
+ anchors.fill:parent
+ style: QStyleItem {
+ id:styleitem
+ elementType: "scrollbar"
+ hover: activeControl != "none"
+ activeControl: "none"
+ sunken: upPressed | downPressed
+ minimum: slider.minimumValue
+ maximum: slider.maximumValue
+ value: slider.value
+ horizontal: orientation == Qt.Horizontal
+ enabled: parent.enabled
+ }
+ }
+
+ property variant handleRect
+ function updateHandle() {
+ handleRect = bgitem.subControlRect("handle")
+ var grooveRect = bgitem.subControlRect("groove");
+ var extra = 0
+ if (orientation == Qt.Vertical) {
+ slider.anchors.topMargin = grooveRect.y + extra
+ slider.anchors.bottomMargin = height - grooveRect.y - grooveRect.height + extra
+ } else {
+ slider.anchors.leftMargin = grooveRect.x + extra
+ slider.anchors.rightMargin = width - grooveRect.x - grooveRect.width + extra
+ }
+ }
+
+ onValueChanged: updateHandle()
+ onMaximumValueChanged: updateHandle()
+ onMinimumValueChanged: updateHandle()
+ Component.onCompleted: updateHandle()
+ Components.Slider {
+ id:slider
+ anchors.fill:parent
+ orientation:scrollbar.orientation
+ leftMargin: (orientation === Qt.Horizontal) ? handleRect.width/2 : handleRect.height/2
+ rightMargin:leftMargin
+ handle: Item { width:orientation == Qt.Vertical ? handleRect.height : handleRect.width;
+ height:orientation == Qt.Vertical ? handleRect.width : handleRect.height}
+ groove:null
+ valueIndicator:null
+ inverted:orientation != Qt.Horizontal
+ }
+}
diff --git a/src/Slider.qml b/src/Slider.qml
new file mode 100644
index 00000000..c6b9c915
--- /dev/null
+++ b/src/Slider.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jens: ContainsMouse breaks drag functionality
+
+Components.Slider{
+ id:slider
+ minimumWidth:200
+
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 15).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ height: buttonHeight
+
+ groove: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"slider"
+ sunken: pressed
+ maximum:slider.maximumValue
+ minimum:slider.minimumValue
+ value:slider.value
+ horizontal:slider.orientation == Qt.Horizontal
+ enabled:slider.enabled
+ }
+ }
+
+ handle: null
+ valueIndicator: null
+}
diff --git a/src/SpinBox.qml b/src/SpinBox.qml
new file mode 100644
index 00000000..2db428ce
--- /dev/null
+++ b/src/SpinBox.qml
@@ -0,0 +1,91 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.SpinBox {
+ id:spinbox
+
+ property variant __upRect;
+ property variant __downRect;
+ property int __margin: (height -16)/2
+
+ // Align height with button
+ topMargin:__margin
+ bottomMargin:__margin
+
+ property int buttonHeight: edititem.sizeFromContents(100, 20).height
+ QStyleItem { id:edititem; elementType:"edit" }
+ height: buttonHeight
+ clip:false
+
+ background:
+ Item {
+ anchors.fill: parent
+ property variant __editRect
+
+ Rectangle {
+ id:editBackground
+ x: __editRect.x - 1
+ y: __editRect.y
+ width: __editRect.width
+ height: __editRect.height
+ }
+
+ Item {
+ id:focusFrame
+ anchors.fill: editBackground
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -6
+ anchors.leftMargin: -5
+ anchors.fill: parent
+ visible:spinbox.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+
+ function updateRect() {
+ __upRect = spinboxbg.subControlRect("up");
+ __downRect = spinboxbg.subControlRect("down");
+ __editRect = spinboxbg.subControlRect("edit");
+ }
+
+ Component.onCompleted:updateRect()
+ onWidthChanged:updateRect()
+ onHeightChanged:updateRect()
+
+ QStyleBackground {
+ id:spinboxbg
+ anchors.fill:parent
+ style: QStyleItem {
+ id: styleitem
+ elementType: "spinbox"
+ sunken: downPressed | upPressed
+ hover: containsMouse
+ focus: spinbox.activeFocus
+ enabled: spinbox.enabled
+ value: (upPressed? 1 : 0) |
+ (downPressed== 1 ? 1<<1 : 0) |
+ (upEnabled? (1<<2) : 0) |
+ (downEnabled == 1 ? (1<<3) : 0)
+ }
+ }
+ }
+
+ up: Item {
+ x: __upRect.x
+ y: __upRect.y
+ width: __upRect.width
+ height: __upRect.height
+ }
+
+ down: Item {
+ x: __downRect.x
+ y: __downRect.y
+ width: __downRect.width
+ height: __downRect.height
+ }
+}
diff --git a/src/Switch.qml b/src/Switch.qml
new file mode 100644
index 00000000..b82817c9
--- /dev/null
+++ b/src/Switch.qml
@@ -0,0 +1,22 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Switch {
+ id:widget
+ minimumWidth:100
+ minimumHeight:30
+
+ groove:QStyleItem {
+ elementType:"edit"
+ sunken: true
+ }
+
+ handle: QStyleItem {
+ elementType:"button"
+ width:widget.width/2
+ height:widget.height-4
+ hover:containsMouse
+ }
+}
+
diff --git a/src/Tab.qml b/src/Tab.qml
new file mode 100644
index 00000000..e258185b
--- /dev/null
+++ b/src/Tab.qml
@@ -0,0 +1,7 @@
+import Qt 4.7
+
+Item {
+ id:tab
+ anchors.fill:parent
+ property string title
+}
diff --git a/src/TabBar.qml b/src/TabBar.qml
new file mode 100644
index 00000000..2d891256
--- /dev/null
+++ b/src/TabBar.qml
@@ -0,0 +1,90 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+
+Item {
+ id: tabbar
+ property int tabHeight: styleitem.sizeFromContents(100, 24).height
+ height: tabHeight
+
+ property Item tabFrame
+ onTabFrameChanged:parent = tabFrame
+ visible: tabFrame ? tabFrame.tabsVisible : true
+ property int __overlap : styleitem.pixelMetric("tabvshift");
+ property string position: tabFrame ? tabFrame.position : "North"
+ property string tabBarAlignment: styleitem.styleHint("tabbaralignment");
+ property int tabOverlap: styleitem.pixelMetric("taboverlap");
+
+ function tab(index) {
+ for (var i = 0; i < tabrow.children.length; ++i) {
+ if (tabrow.children[i].tabindex == index) {
+ return tabrow.children[i]
+ }
+ }
+ return null;
+ }
+
+ QStyleItem {
+ id:styleitem
+ elementType: "tab"
+ text: "generic"
+ }
+
+ Row {
+ id:tabrow
+ states:
+ State {
+ when: tabBarAlignment == "center"
+ name: "centered"
+ AnchorChanges {
+ target:tabrow
+ anchors.horizontalCenter: tabbar.horizontalCenter
+ }
+ }
+ Repeater {
+ id:repeater
+ model: tabFrame ? tabFrame.tabs.length : null
+ delegate: Item {
+ id:tab
+ property int tabindex: index
+ property bool selected : tabFrame.current == index
+ width: textitem.width + 42
+ height: tabHeight
+ z: selected ? 1 : -1
+
+ QStyleBackground {
+ style: QStyleItem {
+ id:style
+ elementType: "tab"
+ selected: tab.selected
+ text: tabbar.position
+
+ activeControl: tabFrame.count == 1 ?
+ "only" :
+ index == 0 ? "beginning" :
+ index == tabFrame.count-1 ? "end" : "middle"
+ }
+ anchors.leftMargin: -tabOverlap + (style.text == "North" && (style.activeControl == "middle" || style.activeControl == "end")
+ && tab.selected ? -__overlap : 0)
+
+ anchors.rightMargin: -tabOverlap + (style.text == "North" && (style.activeControl == "middle" || style.activeControl == "beginning")
+ && tab.selected ? -__overlap : 0)
+ anchors.fill:parent
+ }
+
+ Text {
+ id:textitem
+ anchors.centerIn:parent
+ text: tabFrame.tabs[index].title
+ elide: Text.ElideRight
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: tabFrame.current = index
+ }
+ }
+ }
+ }
+}
diff --git a/src/TabFrame.qml b/src/TabFrame.qml
new file mode 100644
index 00000000..01896e75
--- /dev/null
+++ b/src/TabFrame.qml
@@ -0,0 +1,72 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Item{
+ id: tabWidget
+ width:100
+ height:100
+ property TabBar tabbar
+ property int current: 0
+ property int count: stack.children.length
+ property bool frame:true
+ property bool tabsVisible: true
+ property string position: "North"
+ default property alias tabs : stack.children
+
+ onCurrentChanged: __setOpacities()
+ Component.onCompleted: __setOpacities()
+ onTabbarChanged: {
+ tabbar.tabFrame = tabWidget
+ tabbar.anchors.top = tabWidget.top
+ tabbar.anchors.left = tabWidget.left
+ tabbar.anchors.right = tabWidget.right
+ }
+
+ property int __baseOverlap : style.pixelMetric("tabbaseoverlap");
+ function __setOpacities() {
+ for (var i = 0; i < stack.children.length; ++i) {
+ stack.children[i].opacity = (i == current ? 1 : 0)
+ }
+ }
+
+ QStyleBackground {
+ id: frame
+ z:-1
+ style: QStyleItem {
+ id:style
+ elementType: "tabframe"
+ text: position
+ value: tabbar && tabsVisible && tabbar.tab(current) ? tabbar.tab(current).x : 0
+ minimum: tabbar && tabsVisible && tabbar.tab(current) ? tabbar.tab(current).width : 0
+ }
+ anchors.fill:parent
+ Item {
+ id:stack
+ anchors.fill:parent
+ anchors.margins: frame ? 2 : 0
+ }
+ anchors.topMargin: tabbar && tabsVisible && position == "North" ? tabbar.height - __baseOverlap : 0
+
+ states: [
+ State {
+ name: "South"
+ when: position == "South" && tabbar!= undefined
+ PropertyChanges {
+ target: frame
+ anchors.topMargin: 0
+ anchors.bottomMargin: tabbar ? tabbar.height - __baseOverlap: 0
+ }
+ PropertyChanges {
+ target: tabbar
+ anchors.topMargin: -__baseOverlap
+ }
+ AnchorChanges {
+ target: tabbar
+ anchors.top: frame.bottom
+ anchors.bottom: undefined
+ }
+ }
+ ]
+ }
+}
diff --git a/src/TextArea.qml b/src/TextArea.qml
new file mode 100644
index 00000000..93ad8f3d
--- /dev/null
+++ b/src/TextArea.qml
@@ -0,0 +1,44 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.TextArea {
+ id:textarea
+ leftMargin:12
+ rightMargin:12
+ minimumWidth:200
+ desktopBehavior:true
+ placeholderText:""
+ clip:false
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 14).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ minimumHeight: buttonHeight
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"edit"
+ sunken:true
+ focus:textarea.activeFocus
+ }
+ }
+
+ Item{
+ id:focusFrame
+ anchors.fill: textarea
+ parent:textarea.parent
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ anchors.fill: parent
+ visible:textarea.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+}
diff --git a/src/TextField.qml b/src/TextField.qml
new file mode 100644
index 00000000..260584e9
--- /dev/null
+++ b/src/TextField.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.TextField {
+ id:textfield
+ minimumWidth:200
+ desktopBehavior:true
+ placeholderText:""
+ topMargin:2
+ bottomMargin:2
+ leftMargin:6
+ rightMargin:6
+ width:200
+ height: editItem.sizeFromContents(100, 20).height
+ clip:false
+
+ QStyleItem {
+ id:editItem
+ elementType:"edit"
+ sunken:true
+ focus:textfield.activeFocus
+ hover:containsMouse
+ }
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"edit"
+ sunken:true
+ focus:textfield.activeFocus
+ }
+ }
+
+ Item{
+ id:focusFrame
+ anchors.fill: textfield
+ parent:textfield
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ anchors.fill: parent
+ visible:textfield.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+}
diff --git a/src/TextScrollArea.qml b/src/TextScrollArea.qml
new file mode 100644
index 00000000..2a7deab6
--- /dev/null
+++ b/src/TextScrollArea.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+ScrollArea {
+ id:area
+ color: "white"
+ width: 280
+ height: 120
+ contentWidth: 200
+
+ property alias text: edit.text
+ property alias wrapMode: edit.wrapMode
+ highlightOnFocus: true
+
+ TextEdit {
+ id: edit
+ text: loremIpsum + loremIpsum;
+ wrapMode: TextEdit.WordWrap;
+ width: area.contentWidth
+ selectByMouse:true
+
+ // keep textcursor within scrollarea
+ onCursorRectangleChanged:
+ if (cursorRectangle.y >= area.contentY + area.height - 1.5*cursorRectangle.height)
+ area.contentY = cursorRectangle.y - area.height + 1.5*cursorRectangle.height
+ else if (cursorRectangle.y < area.contentY)
+ area.contentY = cursorRectangle.y
+
+ }
+}
diff --git a/src/ToolBar.qml b/src/ToolBar.qml
new file mode 100644
index 00000000..ce61382e
--- /dev/null
+++ b/src/ToolBar.qml
@@ -0,0 +1,12 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+QStyleBackground {
+ id:styleitem
+ width:200
+ height:60
+
+ style: QStyleItem{elementType:"toolbar"}
+}
+
diff --git a/src/ToolButton.qml b/src/ToolButton.qml
new file mode 100644
index 00000000..98b2dfeb
--- /dev/null
+++ b/src/ToolButton.qml
@@ -0,0 +1,18 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Button {
+ id:button
+ minimumWidth:30
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType: "toolbutton"
+ on: pressed | checked
+ sunken: pressed
+ raised: containsMouse
+ hover: containsMouse
+ }
+ }
+}
diff --git a/src/components/ButtonGroup.js b/src/components/ButtonGroup.js
new file mode 100644
index 00000000..f2d00002
--- /dev/null
+++ b/src/components/ButtonGroup.js
@@ -0,0 +1,127 @@
+var self;
+var clickHandlers = [];
+var visibleButtons = [];
+var nonVisibleButtons = [];
+var direction;
+var exclusive;
+
+function create(that, options) {
+ self = that;
+ direction = options.direction || Qt.Horizontal;
+ exclusive = self.exclusive|| options.exclusive;
+ self.childrenChanged.connect(rebuild);
+// self.widthChanged.connect(resizeChildren);
+ build();
+}
+
+function isButton(item) {
+ if (item && item["__position"] !== undefined)
+ return true;
+ return false;
+}
+
+function hasChecked(item) {
+ if (item && item["checked"] !== undefined)
+ return true;
+ return false;
+}
+
+function destroy() {
+ self.childrenChanged.disconnect(rebuild);
+// self.widthChanged.disconnect(resizeChildren);
+ cleanup();
+}
+
+function build() {
+ visibleButtons = [];
+ nonVisibleButtons = [];
+
+ for (var i = 0, item; (item = self.children[i]); i++) {
+ if (!hasChecked(item))
+ continue;
+
+ item.visibleChanged.connect(rebuild); // Not optimal, but hardly a bottleneck in your app
+ if (!item.visible) {
+ nonVisibleButtons.push(item);
+ continue;
+ }
+ visibleButtons.push(item);
+
+ if (exclusive && hasChecked(item)) {
+ if (item["checkable"]!==undefined) {
+ item.checkable = true;
+ }
+ clickHandlers[i] = checkExclusive(item);
+ item.clicked.connect(clickHandlers[i]);
+ }
+ }
+
+ if (self.checkedButton && !self.checkedButton.visible)
+ self.checkedButton = undefined;
+
+ var nrButtons = visibleButtons.length;
+ if (nrButtons == 0)
+ return;
+
+ if (nrButtons == 1) {
+ finishButton(visibleButtons[0], "only");
+ } else {
+ finishButton(visibleButtons[0], direction == Qt.Horizontal ? "leftmost" : "top");
+ for (var i = 1; i < nrButtons - 1; i++)
+ finishButton(visibleButtons[i], direction == Qt.Horizontal ? "h_middle": "v_middle");
+ finishButton(visibleButtons[nrButtons - 1], direction == Qt.Horizontal ? "rightmost" : "bottom");
+ }
+}
+
+function finishButton(button, position) {
+ if (isButton(button)) {
+ button.__position = position;
+ if (direction == Qt.Vertical) {
+ button.anchors.left = self.left
+ button.anchors.right = self.right
+ }
+ }
+}
+
+function cleanup() {
+ visibleButtons.forEach(function(item, i) {
+ if (clickHandlers[i])
+ item.clicked.disconnect(clickHandlers[i]);
+ item.visibleChanged.disconnect(rebuild);
+ });
+ clickHandlers = [];
+
+ nonVisibleButtons.forEach(function(item, i) {
+ item.visibleChanged.disconnect(rebuild);
+ });
+}
+
+function rebuild() {
+ cleanup();
+ build();
+}
+
+function resizeChildren() {
+ if (direction != Qt.Horizontal)
+ return;
+
+ var extraPixels = self.width % visibleButtons;
+ var buttonSize = (self.width - extraPixels) / visibleButtons;
+ visibleButtons.forEach(function(item, i) {
+ if (!item || !item.visible)
+ return;
+ item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
+ if (extraPixels > 0)
+ extraPixels--;
+ });
+}
+
+function checkExclusive(item) {
+ var button = item;
+ return function() {
+ for (var i = 0, ref; (ref = visibleButtons[i]); i++) {
+ ref.checked = button === ref;
+ }
+ self.checkedButton = button;
+ }
+}
diff --git a/src/components/components.pro b/src/components/components.pro
new file mode 100644
index 00000000..be0663d7
--- /dev/null
+++ b/src/components/components.pro
@@ -0,0 +1,49 @@
+TEMPLATE = subdirs # XXX: Avoid call the linker
+TARGETPATH = Qt/labs/components/custom
+
+symbian {
+ INSTALL_IMPORTS = /resource/qt/imports
+} else {
+ INSTALL_IMPORTS = $$[QT_INSTALL_IMPORTS]
+}
+
+QML_FILES = \
+ qmldir \
+ BasicButton.qml \
+ BusyIndicator.qml \
+ ButtonBlock.qml \
+ ButtonColumn.qml \
+ ButtonRow.qml \
+ ButtonGroup.js \
+ Button.qml \
+ CheckBox.qml \
+ ChoiceList.qml \
+ ProgressBar.qml \
+ RadioButton.qml \
+ ScrollDecorator.qml \
+ ScrollIndicator.qml \
+ Slider.qml \
+ SpinBox.qml \
+ Switch.qml \
+ TextArea.qml \
+ TextField.qml
+
+QML_DIRS = \
+ behaviors \
+ private \
+ styles \
+ visuals
+
+qmlfiles.files = $$QML_FILES
+qmlfiles.sources = $$QML_FILES
+qmlfiles.path = $$INSTALL_IMPORTS/$$TARGETPATH
+
+qmldirs.files = $$QML_DIRS
+qmldirs.sources = $$QML_DIRS
+qmldirs.path = $$INSTALL_IMPORTS/$$TARGETPATH
+
+INSTALLS += qmlfiles qmldirs
+
+symbian {
+ DEPLOYMENT += qmlfiles qmldirs
+}
diff --git a/src/components/qmldir b/src/components/qmldir
new file mode 100644
index 00000000..6e256a81
--- /dev/null
+++ b/src/components/qmldir
@@ -0,0 +1,17 @@
+BasicButton 1.0 BasicButton.qml
+BusyIndicator 1.0 BusyIndicator.qml
+ButtonBlock 1.0 ButtonBlock.qml
+Button 1.0 Button.qml
+ButtonColumn 1.0 ButtonColumn.qml
+ButtonRow 1.0 ButtonRow.qml
+CheckBox 1.0 CheckBox.qml
+ChoiceList 1.0 ChoiceList.qml
+ProgressBar 1.0 ProgressBar.qml
+RadioButton 1.0 RadioButton.qml
+ScrollDecorator 1.0 ScrollDecorator.qml
+ScrollIndicator 1.0 ScrollIndicator.qml
+Slider 1.0 Slider.qml
+SpinBox 1.0 SpinBox.qml
+Switch 1.0 Switch.qml
+TextArea 1.0 TextArea.qml
+TextField 1.0 TextField.qml
diff --git a/src/images/folder_new.png b/src/images/folder_new.png
new file mode 100644
index 00000000..8d8bb9bd
--- /dev/null
+++ b/src/images/folder_new.png
Binary files differ
diff --git a/src/plugin/qmldir b/src/plugin/qmldir
new file mode 100644
index 00000000..e8452efd
--- /dev/null
+++ b/src/plugin/qmldir
@@ -0,0 +1 @@
+plugin styleplugin
diff --git a/src/styleitem/styleitem.pro b/src/styleitem/styleitem.pro
new file mode 100644
index 00000000..b254cd1e
--- /dev/null
+++ b/src/styleitem/styleitem.pro
@@ -0,0 +1,38 @@
+TEMPLATE = lib
+CONFIG += qt plugin
+QT += declarative
+QT += script
+
+TARGET = styleplugin
+
+DESTDIR = ..\\plugin
+OBJECTS_DIR = tmp
+MOC_DIR = tmp
+
+HEADERS += qstyleplugin.h \
+ qstyleitem.h
+
+SOURCES += qstyleplugin.cpp \
+ qstyleitem.cpp
+
+
+OTHER_FILES += \
+ ../widgets/Button.qml \
+ ../widgets/CheckBox.qml \
+ ../widgets/ChoiceList.qml \
+ ../widgets/GroupBox.qml \
+ ../widgets/ProgressBar.qml \
+ ../widgets/RadioButton.qml \
+ ../widgets/ScrollArea.qml \
+ ../widgets/ScrollBar.qml \
+ ../widgets/Slider.qml \
+ ../widgets/SpinBox.qml \
+ ../widgets/Switch.qml \
+ ../widgets/TextArea.qml \
+ ../widgets/TextField.qml \
+ ../widgets/ToolBar.qml \
+ ../widgets/ToolButton.qml \
+ ../gallery.qml \
+ ../widgets/Tab.qml \
+ ../widgets/TabBar.qml \
+ ../widgets/TabFrame.qml
diff --git a/src/widgets/Button.qml b/src/widgets/Button.qml
new file mode 100644
index 00000000..496d37df
--- /dev/null
+++ b/src/widgets/Button.qml
@@ -0,0 +1,27 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Button {
+ id:button
+
+ property int buttonHeight: Math.max(22, styleitem.sizeFromContents(100, 6).height)
+ height: buttonHeight
+
+ QStyleItem {
+ id:styleitem
+ elementType:"button"
+ sunken: pressed
+ raised: !pressed
+ hover: containsMouse
+ enabled:button.enabled
+ text:button.text
+ }
+
+ background:
+ QStyleBackground {
+ style:styleitem
+ anchors.fill:parent
+ }
+}
+
diff --git a/src/widgets/ButtonRow.qml b/src/widgets/ButtonRow.qml
new file mode 100644
index 00000000..623c5f44
--- /dev/null
+++ b/src/widgets/ButtonRow.qml
@@ -0,0 +1,5 @@
+import QtQuick 1.0
+import "../../../components" as Components
+
+Components.ButtonRow {
+}
diff --git a/src/widgets/CheckBox.qml b/src/widgets/CheckBox.qml
new file mode 100644
index 00000000..632dce2d
--- /dev/null
+++ b/src/widgets/CheckBox.qml
@@ -0,0 +1,26 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jb : Size should not depend on background, we should make it consistent
+
+Components.CheckBox{
+ id:checkbox
+ property variant text
+ width:100
+ height:18
+
+ background: QStyleBackground {
+ id:styleitem
+ style:QStyleItem {
+ elementType:"checkbox"
+ sunken:pressed
+ on:checked || pressed
+ hover:containsMouse
+ text:checkbox.text
+ enabled:checkbox.enabled
+ }
+ }
+ checkmark: null
+}
+
diff --git a/src/widgets/ChoiceList.qml b/src/widgets/ChoiceList.qml
new file mode 100644
index 00000000..5015fbef
--- /dev/null
+++ b/src/widgets/ChoiceList.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.ChoiceList {
+ id:choicelist
+
+ property int buttonHeight: buttonitem.sizeFromContents(100, 18).height
+ QStyleItem { id:buttonitem; elementType:"combobox" }
+ height: buttonHeight
+ topMargin:4
+ bottomMargin:4
+
+ QStyleItem {
+ id:styleitem
+ elementType: "combobox"
+ sunken: pressed
+ raised: !pressed
+ hover: containsMouse
+ enabled:choicelist.enabled
+ }
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: styleitem
+ }
+
+ listItem: Item {
+ id:item
+
+ height:22
+ anchors.left:parent.left
+ width:choicelist.width
+ QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType: "menuitem"
+ text: choicelist.model.get(index).text
+ selected: highlighted
+ }
+ }
+ }
+
+ popupFrame: QStyleBackground {
+ property int fw: styleitem.pixelMetric("menupanelwidth");
+ anchors.leftMargin: styleitem.pixelMetric("menuhmargin") + fw
+ anchors.rightMargin: styleitem.pixelMetric("menuhmargin") + fw
+ anchors.topMargin: styleitem.pixelMetric("menuvmargin") + fw
+ anchors.bottomMargin: styleitem.pixelMetric("menuvmargin") + fw
+ style:QStyleItem{elementType:"menu"}
+ }
+}
diff --git a/src/widgets/GroupBox.qml b/src/widgets/GroupBox.qml
new file mode 100644
index 00000000..0d45810d
--- /dev/null
+++ b/src/widgets/GroupBox.qml
@@ -0,0 +1,27 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Item {
+ width:200
+ height:46
+
+ property alias text: styleitem.text
+ default property alias children: content.children
+ property bool checkable: false
+
+ QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ id:styleitem
+ elementType:"groupbox"
+ }
+
+ Item {
+ id:content
+ anchors.topMargin:22
+ anchors.leftMargin:6
+ anchors.fill:parent
+ }
+ }
+}
diff --git a/src/widgets/ProgressBar.qml b/src/widgets/ProgressBar.qml
new file mode 100644
index 00000000..bf29bcac
--- /dev/null
+++ b/src/widgets/ProgressBar.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.ProgressBar {
+ id:progressbar
+
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 15).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ height: buttonHeight
+
+ background: QStyleBackground{
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType:"progressbar"
+
+ // XXX: since desktop uses int instead of real, the progressbar
+ // range [0..1] must be stretched to a good precision
+ property int factor : 1000000
+
+ value: progressbar.value * factor
+ minimum: indeterminate ? 0 : progressbar.minimumValue * factor
+ maximum: indeterminate ? 0 : progressbar.maximumValue * factor
+ enabled: progressbar.enabled
+ }
+ }
+ indeterminateProgress:null
+ progress: null
+}
+
diff --git a/src/widgets/RadioButton.qml b/src/widgets/RadioButton.qml
new file mode 100644
index 00000000..3c2c3e54
--- /dev/null
+++ b/src/widgets/RadioButton.qml
@@ -0,0 +1,26 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jb : Size should not depend on background, we should make it consistent
+
+Components.RadioButton{
+ id:radiobutton
+ property variant text
+ width:110
+ height:18
+
+ background: QStyleBackground {
+
+ style: QStyleItem{
+ elementType:"radiobutton"
+ sunken:pressed
+ on:checked || pressed
+ hover:containsMouse
+ text:radiobutton.text
+ enabled:radiobutton.enabled
+ }
+ }
+ checkmark: null
+}
+
diff --git a/src/widgets/ScrollArea.qml b/src/widgets/ScrollArea.qml
new file mode 100644
index 00000000..3a904dde
--- /dev/null
+++ b/src/widgets/ScrollArea.qml
@@ -0,0 +1,103 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+FocusScope {
+ id:scrollarea
+ width: 100
+ height: 100
+
+ property int contentMargin: 1
+ property int __scrollbarExtent : styleitem.pixelMetric("scrollbarExtent");
+ property int frameWidth: styleitem.pixelMetric("defaultframewidth");
+ property int contentHeight : content.childrenRect.height
+ property int contentWidth: content.childrenRect.width
+ property alias color: flickable.color
+ property bool frame: true
+ property bool highlightOnFocus: false
+
+ default property alias children: content.children
+
+ property int contentY
+ property int contentX
+
+ property bool frameAroundContents: styleitem.styleHint("framearoundcontents")
+
+ onContentYChanged: {
+ vscrollbar.value = contentY
+ }
+
+ onContentXChanged: {
+ hscrollbar.value = contentX
+ }
+
+ QStyleBackground {
+ style: QStyleItem{
+ id:styleitem
+ elementType: frame ? "frame" : ""
+ sunken: true
+ }
+ anchors.fill: parent
+ anchors.rightMargin: (frameAroundContents && vscrollbar.visible) ? vscrollbar.width + 4 : -frameWidth
+ anchors.bottomMargin: (frameAroundContents && hscrollbar.visible) ? hscrollbar.height + 4 : -frameWidth
+ anchors.topMargin: (frameAroundContents && hscrollbar.visible) ? hscrollbar.height + 4 : -frameWidth
+
+ Rectangle {
+ id:flickable
+ color: "transparent"
+ anchors.fill: parent
+ anchors.margins: frame ? 2 : 0
+ clip: true
+
+ Item {
+ id: docmargins
+ anchors.fill:parent
+ anchors.margins:contentMargin
+ Item {
+ id: content
+ x: -scrollarea.contentX
+ y: -scrollarea.contentY
+ }
+ }
+ }
+ }
+
+ ScrollBar {
+ id: hscrollbar
+ orientation: Qt.Horizontal
+ visible: contentWidth > flickable.width
+ maximumValue: contentWidth > flickable.width ? scrollarea.contentWidth - flickable.width : 0
+ minimumValue: 0
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: { return (frame ? 1 : 0) + ( vscrollbar.visible ? __scrollbarExtent : 0) }
+ onValueChanged: contentX = value
+ }
+
+ ScrollBar {
+ id: vscrollbar
+ orientation: Qt.Vertical
+ visible: contentHeight > flickable.height
+ maximumValue: contentHeight > flickable.height ? scrollarea.contentHeight - flickable.height : 0
+ minimumValue: 0
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: { return (frame ? 1 : 0) + (hscrollbar.visible ? __scrollbarExtent : 0) }
+ onValueChanged: contentY = value
+ }
+
+ QStyleBackground {
+ z:2
+ anchors.fill:parent
+ anchors.margins:-2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ visible: highlightOnFocus && parent.activeFocus && styleitem.styleHint("focuswidget")
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+}
diff --git a/src/widgets/ScrollBar.qml b/src/widgets/ScrollBar.qml
new file mode 100644
index 00000000..ea822b62
--- /dev/null
+++ b/src/widgets/ScrollBar.qml
@@ -0,0 +1,109 @@
+import QtQuick 1.1
+import "../../../components" as Components
+import "../plugin"
+
+MouseArea {
+ id:scrollbar
+ property int __scrollbarExtent : styleitem.pixelMetric("scrollbarExtent");
+ implicitWidth:orientation == Qt.Horizontal ? 200 : __scrollbarExtent;
+ implicitHeight:orientation == Qt.Horizontal ? __scrollbarExtent : 200
+
+ property int orientation : Qt.Horizontal
+ property alias minimumValue: slider.minimumValue
+ property alias maximumValue: slider.maximumValue
+ property alias value: slider.value
+
+ property bool upPressed;
+ property bool downPressed;
+ property bool __autoincrement: false
+
+ // Update hover item
+ onEntered: styleitem.activeControl = bgitem.hitTest(mouseX, mouseY)
+ onExited: styleitem.activeControl = "none"
+ onMouseXChanged: styleitem.activeControl = bgitem.hitTest(mouseX, mouseY)
+ hoverEnabled:true
+
+ Timer { running: upPressed || downPressed; interval: 350 ; onTriggered: __autoincrement = true }
+ Timer { running: __autoincrement; interval: 60 ; repeat: true ;
+ onTriggered: upPressed ? decrement() : increment() }
+
+ onPressed: {
+ var control = bgitem.hitTest(mouseX,mouseY)
+ if (control == "up") {
+ upPressed = true
+ } else if (control == "down") {
+ downPressed = true
+ }
+ }
+
+ onReleased: {
+ __autoincrement = false;
+ if (upPressed) {
+ upPressed = false;
+ decrement()
+ } else if (downPressed) {
+ increment()
+ downPressed = false;
+ }
+ }
+
+ function increment() {
+ value += 30
+ if (value > maximumValue)
+ value = maximumValue
+ }
+
+ function decrement() {
+ value -= 30
+ if (value < minimumValue)
+ value = minimumValue
+ }
+
+ QStyleBackground {
+ id:bgitem
+ anchors.fill:parent
+ style: QStyleItem {
+ id:styleitem
+ elementType: "scrollbar"
+ hover: activeControl != "none"
+ activeControl: "none"
+ sunken: upPressed | downPressed
+ minimum: slider.minimumValue
+ maximum: slider.maximumValue
+ value: slider.value
+ horizontal: orientation == Qt.Horizontal
+ enabled: parent.enabled
+ }
+ }
+
+ property variant handleRect
+ function updateHandle() {
+ handleRect = bgitem.subControlRect("handle")
+ var grooveRect = bgitem.subControlRect("groove");
+ var extra = 0
+ if (orientation == Qt.Vertical) {
+ slider.anchors.topMargin = grooveRect.y + extra
+ slider.anchors.bottomMargin = height - grooveRect.y - grooveRect.height + extra
+ } else {
+ slider.anchors.leftMargin = grooveRect.x + extra
+ slider.anchors.rightMargin = width - grooveRect.x - grooveRect.width + extra
+ }
+ }
+
+ onValueChanged: updateHandle()
+ onMaximumValueChanged: updateHandle()
+ onMinimumValueChanged: updateHandle()
+ Component.onCompleted: updateHandle()
+ Components.Slider {
+ id:slider
+ anchors.fill:parent
+ orientation:scrollbar.orientation
+ leftMargin: (orientation === Qt.Horizontal) ? handleRect.width/2 : handleRect.height/2
+ rightMargin:leftMargin
+ handle: Item { width:orientation == Qt.Vertical ? handleRect.height : handleRect.width;
+ height:orientation == Qt.Vertical ? handleRect.width : handleRect.height}
+ groove:null
+ valueIndicator:null
+ inverted:orientation != Qt.Horizontal
+ }
+}
diff --git a/src/widgets/Slider.qml b/src/widgets/Slider.qml
new file mode 100644
index 00000000..c6b9c915
--- /dev/null
+++ b/src/widgets/Slider.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+// jens: ContainsMouse breaks drag functionality
+
+Components.Slider{
+ id:slider
+ minimumWidth:200
+
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 15).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ height: buttonHeight
+
+ groove: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"slider"
+ sunken: pressed
+ maximum:slider.maximumValue
+ minimum:slider.minimumValue
+ value:slider.value
+ horizontal:slider.orientation == Qt.Horizontal
+ enabled:slider.enabled
+ }
+ }
+
+ handle: null
+ valueIndicator: null
+}
diff --git a/src/widgets/SpinBox.qml b/src/widgets/SpinBox.qml
new file mode 100644
index 00000000..2db428ce
--- /dev/null
+++ b/src/widgets/SpinBox.qml
@@ -0,0 +1,91 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.SpinBox {
+ id:spinbox
+
+ property variant __upRect;
+ property variant __downRect;
+ property int __margin: (height -16)/2
+
+ // Align height with button
+ topMargin:__margin
+ bottomMargin:__margin
+
+ property int buttonHeight: edititem.sizeFromContents(100, 20).height
+ QStyleItem { id:edititem; elementType:"edit" }
+ height: buttonHeight
+ clip:false
+
+ background:
+ Item {
+ anchors.fill: parent
+ property variant __editRect
+
+ Rectangle {
+ id:editBackground
+ x: __editRect.x - 1
+ y: __editRect.y
+ width: __editRect.width
+ height: __editRect.height
+ }
+
+ Item {
+ id:focusFrame
+ anchors.fill: editBackground
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -6
+ anchors.leftMargin: -5
+ anchors.fill: parent
+ visible:spinbox.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+
+ function updateRect() {
+ __upRect = spinboxbg.subControlRect("up");
+ __downRect = spinboxbg.subControlRect("down");
+ __editRect = spinboxbg.subControlRect("edit");
+ }
+
+ Component.onCompleted:updateRect()
+ onWidthChanged:updateRect()
+ onHeightChanged:updateRect()
+
+ QStyleBackground {
+ id:spinboxbg
+ anchors.fill:parent
+ style: QStyleItem {
+ id: styleitem
+ elementType: "spinbox"
+ sunken: downPressed | upPressed
+ hover: containsMouse
+ focus: spinbox.activeFocus
+ enabled: spinbox.enabled
+ value: (upPressed? 1 : 0) |
+ (downPressed== 1 ? 1<<1 : 0) |
+ (upEnabled? (1<<2) : 0) |
+ (downEnabled == 1 ? (1<<3) : 0)
+ }
+ }
+ }
+
+ up: Item {
+ x: __upRect.x
+ y: __upRect.y
+ width: __upRect.width
+ height: __upRect.height
+ }
+
+ down: Item {
+ x: __downRect.x
+ y: __downRect.y
+ width: __downRect.width
+ height: __downRect.height
+ }
+}
diff --git a/src/widgets/Switch.qml b/src/widgets/Switch.qml
new file mode 100644
index 00000000..b82817c9
--- /dev/null
+++ b/src/widgets/Switch.qml
@@ -0,0 +1,22 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Switch {
+ id:widget
+ minimumWidth:100
+ minimumHeight:30
+
+ groove:QStyleItem {
+ elementType:"edit"
+ sunken: true
+ }
+
+ handle: QStyleItem {
+ elementType:"button"
+ width:widget.width/2
+ height:widget.height-4
+ hover:containsMouse
+ }
+}
+
diff --git a/src/widgets/Tab.qml b/src/widgets/Tab.qml
new file mode 100644
index 00000000..e258185b
--- /dev/null
+++ b/src/widgets/Tab.qml
@@ -0,0 +1,7 @@
+import Qt 4.7
+
+Item {
+ id:tab
+ anchors.fill:parent
+ property string title
+}
diff --git a/src/widgets/TabBar.qml b/src/widgets/TabBar.qml
new file mode 100644
index 00000000..2d891256
--- /dev/null
+++ b/src/widgets/TabBar.qml
@@ -0,0 +1,90 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+
+Item {
+ id: tabbar
+ property int tabHeight: styleitem.sizeFromContents(100, 24).height
+ height: tabHeight
+
+ property Item tabFrame
+ onTabFrameChanged:parent = tabFrame
+ visible: tabFrame ? tabFrame.tabsVisible : true
+ property int __overlap : styleitem.pixelMetric("tabvshift");
+ property string position: tabFrame ? tabFrame.position : "North"
+ property string tabBarAlignment: styleitem.styleHint("tabbaralignment");
+ property int tabOverlap: styleitem.pixelMetric("taboverlap");
+
+ function tab(index) {
+ for (var i = 0; i < tabrow.children.length; ++i) {
+ if (tabrow.children[i].tabindex == index) {
+ return tabrow.children[i]
+ }
+ }
+ return null;
+ }
+
+ QStyleItem {
+ id:styleitem
+ elementType: "tab"
+ text: "generic"
+ }
+
+ Row {
+ id:tabrow
+ states:
+ State {
+ when: tabBarAlignment == "center"
+ name: "centered"
+ AnchorChanges {
+ target:tabrow
+ anchors.horizontalCenter: tabbar.horizontalCenter
+ }
+ }
+ Repeater {
+ id:repeater
+ model: tabFrame ? tabFrame.tabs.length : null
+ delegate: Item {
+ id:tab
+ property int tabindex: index
+ property bool selected : tabFrame.current == index
+ width: textitem.width + 42
+ height: tabHeight
+ z: selected ? 1 : -1
+
+ QStyleBackground {
+ style: QStyleItem {
+ id:style
+ elementType: "tab"
+ selected: tab.selected
+ text: tabbar.position
+
+ activeControl: tabFrame.count == 1 ?
+ "only" :
+ index == 0 ? "beginning" :
+ index == tabFrame.count-1 ? "end" : "middle"
+ }
+ anchors.leftMargin: -tabOverlap + (style.text == "North" && (style.activeControl == "middle" || style.activeControl == "end")
+ && tab.selected ? -__overlap : 0)
+
+ anchors.rightMargin: -tabOverlap + (style.text == "North" && (style.activeControl == "middle" || style.activeControl == "beginning")
+ && tab.selected ? -__overlap : 0)
+ anchors.fill:parent
+ }
+
+ Text {
+ id:textitem
+ anchors.centerIn:parent
+ text: tabFrame.tabs[index].title
+ elide: Text.ElideRight
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: tabFrame.current = index
+ }
+ }
+ }
+ }
+}
diff --git a/src/widgets/TabFrame.qml b/src/widgets/TabFrame.qml
new file mode 100644
index 00000000..01896e75
--- /dev/null
+++ b/src/widgets/TabFrame.qml
@@ -0,0 +1,72 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Item{
+ id: tabWidget
+ width:100
+ height:100
+ property TabBar tabbar
+ property int current: 0
+ property int count: stack.children.length
+ property bool frame:true
+ property bool tabsVisible: true
+ property string position: "North"
+ default property alias tabs : stack.children
+
+ onCurrentChanged: __setOpacities()
+ Component.onCompleted: __setOpacities()
+ onTabbarChanged: {
+ tabbar.tabFrame = tabWidget
+ tabbar.anchors.top = tabWidget.top
+ tabbar.anchors.left = tabWidget.left
+ tabbar.anchors.right = tabWidget.right
+ }
+
+ property int __baseOverlap : style.pixelMetric("tabbaseoverlap");
+ function __setOpacities() {
+ for (var i = 0; i < stack.children.length; ++i) {
+ stack.children[i].opacity = (i == current ? 1 : 0)
+ }
+ }
+
+ QStyleBackground {
+ id: frame
+ z:-1
+ style: QStyleItem {
+ id:style
+ elementType: "tabframe"
+ text: position
+ value: tabbar && tabsVisible && tabbar.tab(current) ? tabbar.tab(current).x : 0
+ minimum: tabbar && tabsVisible && tabbar.tab(current) ? tabbar.tab(current).width : 0
+ }
+ anchors.fill:parent
+ Item {
+ id:stack
+ anchors.fill:parent
+ anchors.margins: frame ? 2 : 0
+ }
+ anchors.topMargin: tabbar && tabsVisible && position == "North" ? tabbar.height - __baseOverlap : 0
+
+ states: [
+ State {
+ name: "South"
+ when: position == "South" && tabbar!= undefined
+ PropertyChanges {
+ target: frame
+ anchors.topMargin: 0
+ anchors.bottomMargin: tabbar ? tabbar.height - __baseOverlap: 0
+ }
+ PropertyChanges {
+ target: tabbar
+ anchors.topMargin: -__baseOverlap
+ }
+ AnchorChanges {
+ target: tabbar
+ anchors.top: frame.bottom
+ anchors.bottom: undefined
+ }
+ }
+ ]
+ }
+}
diff --git a/src/widgets/TextArea.qml b/src/widgets/TextArea.qml
new file mode 100644
index 00000000..93ad8f3d
--- /dev/null
+++ b/src/widgets/TextArea.qml
@@ -0,0 +1,44 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.TextArea {
+ id:textarea
+ leftMargin:12
+ rightMargin:12
+ minimumWidth:200
+ desktopBehavior:true
+ placeholderText:""
+ clip:false
+ // Align with button
+ property int buttonHeight: buttonitem.sizeFromContents(100, 14).height
+ QStyleItem { id:buttonitem; elementType:"button" }
+ minimumHeight: buttonHeight
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"edit"
+ sunken:true
+ focus:textarea.activeFocus
+ }
+ }
+
+ Item{
+ id:focusFrame
+ anchors.fill: textarea
+ parent:textarea.parent
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ anchors.fill: parent
+ visible:textarea.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+}
diff --git a/src/widgets/TextField.qml b/src/widgets/TextField.qml
new file mode 100644
index 00000000..260584e9
--- /dev/null
+++ b/src/widgets/TextField.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.TextField {
+ id:textfield
+ minimumWidth:200
+ desktopBehavior:true
+ placeholderText:""
+ topMargin:2
+ bottomMargin:2
+ leftMargin:6
+ rightMargin:6
+ width:200
+ height: editItem.sizeFromContents(100, 20).height
+ clip:false
+
+ QStyleItem {
+ id:editItem
+ elementType:"edit"
+ sunken:true
+ focus:textfield.activeFocus
+ hover:containsMouse
+ }
+
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem{
+ elementType:"edit"
+ sunken:true
+ focus:textfield.activeFocus
+ }
+ }
+
+ Item{
+ id:focusFrame
+ anchors.fill: textfield
+ parent:textfield
+ visible:framestyle.styleHint("focuswidget")
+ QStyleBackground{
+ anchors.margins: -2
+ anchors.rightMargin:-4
+ anchors.bottomMargin:-4
+ anchors.fill: parent
+ visible:textfield.activeFocus
+ style: QStyleItem {
+ id:framestyle
+ elementType:"focusframe"
+ }
+ }
+ }
+}
diff --git a/src/widgets/TextScrollArea.qml b/src/widgets/TextScrollArea.qml
new file mode 100644
index 00000000..2a7deab6
--- /dev/null
+++ b/src/widgets/TextScrollArea.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+ScrollArea {
+ id:area
+ color: "white"
+ width: 280
+ height: 120
+ contentWidth: 200
+
+ property alias text: edit.text
+ property alias wrapMode: edit.wrapMode
+ highlightOnFocus: true
+
+ TextEdit {
+ id: edit
+ text: loremIpsum + loremIpsum;
+ wrapMode: TextEdit.WordWrap;
+ width: area.contentWidth
+ selectByMouse:true
+
+ // keep textcursor within scrollarea
+ onCursorRectangleChanged:
+ if (cursorRectangle.y >= area.contentY + area.height - 1.5*cursorRectangle.height)
+ area.contentY = cursorRectangle.y - area.height + 1.5*cursorRectangle.height
+ else if (cursorRectangle.y < area.contentY)
+ area.contentY = cursorRectangle.y
+
+ }
+}
diff --git a/src/widgets/ToolBar.qml b/src/widgets/ToolBar.qml
new file mode 100644
index 00000000..ce61382e
--- /dev/null
+++ b/src/widgets/ToolBar.qml
@@ -0,0 +1,12 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+QStyleBackground {
+ id:styleitem
+ width:200
+ height:60
+
+ style: QStyleItem{elementType:"toolbar"}
+}
+
diff --git a/src/widgets/ToolButton.qml b/src/widgets/ToolButton.qml
new file mode 100644
index 00000000..98b2dfeb
--- /dev/null
+++ b/src/widgets/ToolButton.qml
@@ -0,0 +1,18 @@
+import QtQuick 1.0
+import "../../../components" as Components
+import "../plugin"
+
+Components.Button {
+ id:button
+ minimumWidth:30
+ background: QStyleBackground {
+ anchors.fill:parent
+ style: QStyleItem {
+ elementType: "toolbutton"
+ on: pressed | checked
+ sunken: pressed
+ raised: containsMouse
+ hover: containsMouse
+ }
+ }
+}