summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-11-02 13:10:37 +0100
committerSamuel Rødal <samuel.rodal@nokia.com>2011-11-02 13:11:10 +0100
commit7855aaff6271c7544b68e31d744443bfdeb92e96 (patch)
treefad5fb5d7853914c7731327783ad0085e02aece6 /components
parent8b27785d0f33c2f4f33768e5ecf6293480d047f3 (diff)
parent0959b13bd88fe195d0715820c750c3e5c8ba8fb1 (diff)
downloadqtquickcontrols-7855aaff6271c7544b68e31d744443bfdeb92e96.tar.gz
Attempted merge of origin/master
Prepare for borkenness Reviewed-by: Jens Reviewed-by: Tor Arne Conflicts: components/Button.qml components/ButtonRow.qml components/CheckBox.qml components/ChoiceList.qml components/ContextMenu.qml components/Dial.qml components/Frame.qml components/GroupBox.qml components/ProgressBar.qml components/RadioButton.qml components/ScrollArea.qml components/ScrollBar.qml components/Slider.qml components/SpinBox.qml components/Switch.qml components/Tab.qml components/TabBar.qml components/TabFrame.qml components/TableColumn.qml components/TableView.qml components/TextArea.qml components/TextField.qml components/ToolBar.qml components/ToolButton.qml components/custom/BasicButton.qml components/custom/Button.qml components/custom/CheckBox.qml components/custom/ChoiceList.qml components/custom/GroupBox.qml components/custom/ProgressBar.qml components/custom/Slider.qml components/custom/SpinBox.qml components/custom/TextField.qml components/custom/behaviors/ButtonBehavior.qml components/custom/behaviors/ModalPopupBehavior.qml components/custom/private/ChoiceListPopup.qml examples/Gallery.qml src/qstyleitem.cpp src/qtmenuitem.h src/qtoplevelwindow.cpp src/qwheelarea.h src/qwindowitem.cpp src/styleitem/qwheelarea.cpp src/styleitem/styleitem.pro
Diffstat (limited to 'components')
-rw-r--r--components/ApplicationWindow.qml41
-rw-r--r--components/Button.qml33
-rw-r--r--components/ButtonColumn.qml5
-rw-r--r--components/CheckBox.qml40
-rw-r--r--components/ChoiceList.qml64
-rw-r--r--components/ComboBox.qml24
-rw-r--r--components/Dial.qml77
-rw-r--r--components/Dialog.qml123
-rw-r--r--components/Frame.qml7
-rw-r--r--components/GroupBox.qml8
-rw-r--r--components/Label.qml8
-rw-r--r--components/MenuItem.qml3
-rw-r--r--components/ProgressBar.qml12
-rw-r--r--components/RadioButton.qml38
-rw-r--r--components/ScrollArea.qml151
-rw-r--r--components/ScrollBar.qml5
-rw-r--r--components/Slider.qml21
-rw-r--r--components/SpinBox.qml25
-rw-r--r--components/SplitterColumn.qml123
-rw-r--r--components/SplitterRow.qml132
-rw-r--r--components/StatusBar.qml12
-rw-r--r--components/Switch.qml21
-rw-r--r--components/TabBar.qml22
-rw-r--r--components/TabFrame.qml48
-rw-r--r--components/TableColumn.qml7
-rw-r--r--components/TableView.qml342
-rw-r--r--components/TextArea.qml13
-rw-r--r--components/TextField.qml13
-rw-r--r--components/ToolBar.qml8
-rw-r--r--components/ToolButton.qml41
-rw-r--r--components/components.pro12
-rw-r--r--components/custom/BasicButton.qml18
-rw-r--r--components/custom/ButtonColumn.qml6
-rw-r--r--components/custom/ButtonGroup.js4
-rw-r--r--components/custom/ButtonRow.qml9
-rw-r--r--components/custom/CheckBox.qml14
-rw-r--r--components/custom/ChoiceList.qml50
-rw-r--r--components/custom/GroupBox.qml54
-rw-r--r--components/custom/ProgressBar.qml3
-rw-r--r--components/custom/SpinBox.qml6
-rw-r--r--components/custom/Splitter.qml405
-rw-r--r--components/custom/SplitterRow.qml494
-rw-r--r--components/custom/TextField.qml10
-rw-r--r--components/custom/components.pro3
-rw-r--r--components/custom/private/ChoiceListPopup.qml322
-rw-r--r--components/custom/qmldir2
-rw-r--r--components/private/ScrollAreaHelper.qml83
-rw-r--r--components/qmldir6
48 files changed, 1503 insertions, 1465 deletions
diff --git a/components/ApplicationWindow.qml b/components/ApplicationWindow.qml
new file mode 100644
index 00000000..bb19a91e
--- /dev/null
+++ b/components/ApplicationWindow.qml
@@ -0,0 +1,41 @@
+import QtQuick 1.1
+
+Window {
+ width: 320
+ height: 240
+
+ property alias toolBar: toolBarArea.data
+ property alias statusBar: statusBarArea.data
+ default property alias data: contentArea.data
+
+ SystemPalette {id: syspal}
+
+
+ Rectangle {
+ anchors.fill: parent
+ color: syspal.button
+ }
+
+
+ Column {
+ id: toolBarArea
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+
+ Item {
+ id: contentArea
+ anchors.top: toolBarArea.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: statusBarArea.top
+ }
+
+ Column {
+ id: statusBarArea
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+}
diff --git a/components/Button.qml b/components/Button.qml
index 7dbbb158..9f456d31 100644
--- a/components/Button.qml
+++ b/components/Button.qml
@@ -3,15 +3,21 @@ import "custom" as Components
import QtDesktop 0.1
Components.Button {
- id:button
+ id: button
- width: Math.max(80, sizehint.width)
- height: Math.max(22, sizehint.height)
+ implicitWidth: Math.max(72, backgroundItem.implicitWidth)
+ implicitHeight: Math.max(22, backgroundItem.implicitHeight)
- property variant sizehint: backgroundItem.sizeFromContents(80, 6)
- property bool defaultbutton
- property string hint
+ property alias containsMouse: tooltip.containsMouse
+ property bool defaultbutton: false
+ property string styleHint
+ TooltipArea {
+ // Note this will eat hover events
+ id: tooltip
+ anchors.fill: parent
+ text: button.tooltip
+ }
background: StyleItem {
id: styleitem
@@ -21,18 +27,11 @@ Components.Button {
raised: !(pressed || checked)
hover: containsMouse
text: iconSource === "" ? "" : button.text
- focus: button.focus
- hint: button.hint
+ hasFocus: button.focus
+ hint: button.styleHint
// If no icon, let the style do the drawing
- activeControl: focus ? "default" : ""
- Connections{
- target: button
- onToolTipTriggered: styleitem.showTip()
- }
- function showTip(){
- showToolTip(tooltip);
- }
+ activeControl: defaultbutton ? "default" : "f"
}
label: Item {
@@ -57,6 +56,6 @@ Components.Button {
}
}
}
- Keys.onSpacePressed:clicked()
+ Keys.onSpacePressed:animateClick()
}
diff --git a/components/ButtonColumn.qml b/components/ButtonColumn.qml
new file mode 100644
index 00000000..0ba25f91
--- /dev/null
+++ b/components/ButtonColumn.qml
@@ -0,0 +1,5 @@
+import QtQuick 1.1
+import "custom" as Components
+
+Components.ButtonColumn {
+}
diff --git a/components/CheckBox.qml b/components/CheckBox.qml
index 11caa92a..9eed75e8 100644
--- a/components/CheckBox.qml
+++ b/components/CheckBox.qml
@@ -4,24 +4,34 @@ import QtDesktop 0.1
// jb : Size should not depend on background, we should make it consistent
-Components.CheckBox{
- id:checkbox
+Components.CheckBox {
+ id: checkbox
property string text
- property string hint
- width: Math.max(110, backgroundItem.textWidth(text) + 40)
- height: 20
+ property string styleHint
+
+ implicitWidth: Math.max(120, backgroundItem.implicitWidth)
+ implicitHeight: backgroundItem.implicitHeight
background: StyleItem {
- id:styleitem
- elementType:"checkbox"
- sunken:pressed
- on:checked || pressed
- hover:containsMouse
- text:checkbox.text
- enabled:checkbox.enabled
- focus:checkbox.focus
- hint:checkbox.hint
+ elementType: "checkbox"
+ sunken: pressed
+ on: checked || pressed
+ hover: containsMouse
+ enabled: checkbox.enabled
+ hasFocus: checkbox.activeFocus
+ hint: checkbox.styleHint
+ contentHeight: textitem.implicitHeight
+ contentWidth: textitem.implicitWidth + indicatorWidth
+ property int indicatorWidth: pixelMetric("indicatorwidth") + 2
+ Text {
+ id: textitem
+ text: checkbox.text
+ anchors.left: parent.left
+ anchors.leftMargin: parent.indicatorWidth
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ elide: Text.ElideRight
+ }
}
- Keys.onSpacePressed:checked = !checked
}
diff --git a/components/ChoiceList.qml b/components/ChoiceList.qml
deleted file mode 100644
index aea5b199..00000000
--- a/components/ChoiceList.qml
+++ /dev/null
@@ -1,64 +0,0 @@
-import QtQuick 2.0
-import "custom" as Components
-import "plugin"
-import "shadereffects"
-
-Components.ChoiceList {
-
- id: choicelist
-
- property int buttonHeight: backgroundItem.sizeFromContents(100, 18).height
- property int buttonWidth: backgroundItem.sizeFromContents(100, 18).width
-
- property string hint
-
- height: buttonHeight
- width: buttonWidth
- topMargin: 4
- bottomMargin: 4
-
- background: StyleItem {
- anchors.fill: parent
- elementType: "combobox"
- sunken: pressed
- raised: !pressed
- hover: containsMouse
- enabled: choicelist.enabled
- text: currentItemText
- focus: choicelist.focus
- hint: choicelist.hint
- }
-
- listItem: Item {
- id:item
-
- height: 22
- anchors.left: parent.left
- width: choicelist.width
- StyleItem {
- anchors.fill: parent
- elementType: "comboboxitem"
- text: itemText
- selected: highlighted
-
- }
- }
- popupFrame: StyleItem {
- property string popupLocation: backgroundItem.styleHint("comboboxpopup") ? "center" : "below"
- anchors.leftMargin: backgroundItem.pixelMetric("menuhmargin") + fw
- anchors.rightMargin: backgroundItem.pixelMetric("menuhmargin") + fw
- anchors.topMargin: backgroundItem.pixelMetric("menuvmargin") + fw
- anchors.bottomMargin: backgroundItem.pixelMetric("menuvmargin") + fw
-
- property string behavior: backgroundItem.styleHint("comboboxpopup") ? "MacOS" : "Windows"
- property int fw: backgroundItem.pixelMetric("menupanelwidth");
- QStyleItem {
- id: menu
- anchors.fill: parent
- elementType: "menu"
- }
- DropShadow {
- itemSource: menu
- }
- }
-}
diff --git a/components/ComboBox.qml b/components/ComboBox.qml
index 61337f10..81fadf1d 100644
--- a/components/ComboBox.qml
+++ b/components/ComboBox.qml
@@ -1,4 +1,4 @@
-import QtQuick 1.0
+import QtQuick 1.1
import "custom" as Custom
import QtDesktop 0.1
@@ -63,7 +63,7 @@ Custom.BasicButton {
property alias hoveredIndex: popup.hoveredIndex
property alias selectedText: popup.selectedText
property alias hoveredText: popup.hoveredText
- property string hint
+ property string styleHint
background: StyleItem {
anchors.fill: parent
@@ -73,20 +73,20 @@ Custom.BasicButton {
hover: comboBox.containsMouse
enabled: comboBox.enabled
text: comboBox.selectedText
- focus: comboBox.focus
+ hasFocus: comboBox.focus
+ contentHeight: 18
}
-// ToDo: adjust margins so that selected popup label
-// centers directly above button label when
-// popup.centerOnSelectedText === true
-// property int leftMargin: 0
-// property int topMargin: 0
-// property int rightMargin: 0
-// property int bottomMargin: 0
+// ToDo: adjust margins so that selected popup label
+// centers directly above button label when
+// popup.centerOnSelectedText === true
- width: backgroundItem.sizeFromContents(100, 18).height
+
+ width: implicitWidth
+ height: implicitHeight
+ implicitWidth: Math.max(80, backgroundItem.implicitWidth)
+ implicitHeight: backgroundItem.implicitHeight
onWidthChanged: popup.setMinimumWidth(width)
- height: backgroundItem.sizeFromContents(100, 18).height
checkable: false
onPressedChanged: if (pressed) popup.visible = true
diff --git a/components/Dial.qml b/components/Dial.qml
index 2972e1f7..61a03347 100644
--- a/components/Dial.qml
+++ b/components/Dial.qml
@@ -1,22 +1,51 @@
+/****************************************************************************
+**
+** 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 2.0
+
import "custom" as Components
import QtDesktop 0.1
// jens: ContainsMouse breaks drag functionality
-StyleItem {
+Item {
id: dial
- width:100
- height:100
+ width: 100
+ height: 100
property alias maximumValue: range.maximumValue
property alias minimumValue: range.minimumValue
property alias containsMouse: mouseArea.containsMouse
property alias value: range.value
+ property alias stepSize: range.stepSize
property bool wrapping: false
- property bool tickmarks: true // not implemented
+ property bool tickmarksEnabled: false
+ property bool activeFocusOnPress: false
RangeModel {
id: range
@@ -40,7 +69,7 @@ StyleItem {
}
onPressed: {
value = valueFromPoint(mouseX, mouseY)
- dial.focus = true
+ if (activeFocusOnPress) dial.focus = true
}
onReleased:inDrag = false;
@@ -76,7 +105,27 @@ StyleItem {
return maximumValue - bound(v/100)
}
}
-
+ StyleItem {
+ anchors.fill: parent
+ elementType: "dial"
+ hasFocus: dial.focus
+ sunken: mouseArea.pressed
+ maximum: range.maximumValue * 100
+ minimum: range.minimumValue * 100
+ value: visualPos * 100
+ enabled: dial.enabled
+ step: range.stepSize * 100
+ activeControl: tickmarksEnabled ? "tick" : ""
+ property double visualPos : range.value
+
+ Behavior on visualPos {
+ enabled: !mouseArea.inDrag
+ NumberAnimation {
+ duration: 300
+ easing.type: Easing.OutSine
+ }
+ }
+ }
WheelArea {
id: wheelarea
anchors.fill: parent
@@ -94,20 +143,4 @@ StyleItem {
value += horizontalDelta/4*step
}
}
-
- elementType:"dial"
- sunken: mouseArea.pressed
- maximum: range.maximumValue*90
- minimum: range.minimumValue*90
- focus:dial.focus
- value: visualPos*90
- enabled: dial.enabled
- property double visualPos : range.value
- Behavior on visualPos {
- enabled: !mouseArea.inDrag
- NumberAnimation {
- duration: 300
- easing.type: Easing.OutSine
- }
- }
}
diff --git a/components/Dialog.qml b/components/Dialog.qml
new file mode 100644
index 00000000..22fd263f
--- /dev/null
+++ b/components/Dialog.qml
@@ -0,0 +1,123 @@
+import QtQuick 1.1
+
+Window {
+ id: dialog
+
+ width: 400
+ height: 200
+
+ signal closed
+ signal accepted
+ signal rejected
+ signal buttonClicked
+
+ property QtObject clickedButton: null
+
+ property int noRole: 0
+ property int acceptRole: 1
+ property int rejectRole: 2
+ property int helpRole: 3
+
+ property int ok: 0x00000400
+ property int cancel: 0x00400000
+ property int close: 0x00200000
+ property int help: 0x02000000
+
+ property int buttons: ok | cancel
+
+ modal: false
+
+ default property alias data: content.data
+
+ Item {
+ id: content
+ anchors.topMargin:16
+ anchors.margins: 16
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.left: parent.left
+ anchors.bottom: buttonrow.top
+ }
+
+ // Dialogs should center on parent
+ onVisibleChanged: center()
+
+ Row {
+ property bool mac: (style.style == "mac")
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.margins: 16
+ anchors.topMargin:0
+ anchors.bottomMargin: style.isMac ? 12 : 8
+ spacing: 6
+
+ Button {
+ id: helpbutton
+ property int role: helpRole
+ visible: buttons & help
+ text: "Help"
+ focus: false
+ Component.onCompleted: if (style.isMac) width = 22
+ background: style.isMac ? machelpdelegate : cancelbutton.background
+ onClicked: {
+ clickedButton = helpbutton
+ buttonClicked()
+ }
+ Component {
+ id: machelpdelegate
+ StyleItem {
+ anchors.fill: parent
+ elementType: "machelpbutton"
+ width: 22
+ height: 22
+ sunken: helpbutton.pressed
+ anchors.centerIn: parent
+ }
+ }
+ }
+ }
+ Row {
+ id: buttonrow
+ spacing: 6
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.margins: 16
+ anchors.topMargin: 0
+ anchors.bottomMargin: 8
+ layoutDirection: style.isMac ? Qt.LeftToRight : Qt.RightToLeft
+
+ Button {
+ id: cancelbutton
+ visible: buttons & cancel
+ property int role: rejectRole
+ text: "Cancel"
+ onClicked: {
+ visible: dialog.visible = false
+ clickedButton = cancelbutton
+ rejected()
+ closed()
+ buttonClicked(role)
+ }
+ }
+ Button {
+ id: okbutton
+ property int role: acceptRole
+ visible: buttons & ok
+ text: "OK"
+ defaultbutton: true
+ onClicked: {
+ visible: dialog.visible = false
+ clickedButton = okbutton
+ accepted()
+ closed()
+ buttonClicked()
+ }
+ }
+ }
+ StyleItem {
+ id: style
+ visible: false
+ property bool isMac: (style.style == "mac")
+
+ }
+}
diff --git a/components/Frame.qml b/components/Frame.qml
index ee66bd63..bc7de579 100644
--- a/components/Frame.qml
+++ b/components/Frame.qml
@@ -3,11 +3,12 @@ import "custom" as Components
import QtDesktop 0.1
Item {
- default property alias children: content.children
- width: Math.max(100, content.childrenRect.width + 2 * content.frameWidth)
- height: Math.max(100, content.childrenRect.height + 2 * content.frameWidth)
+ default property alias data: content.data
+ implicitWidth: adjustToContentSize ? content.childrenRect.width + 2 * content.frameWidth : 30
+ implicitHeight: adjustToContentSize ? content.childrenRect.height + 2 * content.frameWidth : 30
property alias raised: style.raised
property alias sunken: style.sunken
+ property bool adjustToContentSize: false
StyleItem {
id: style
anchors.fill: parent
diff --git a/components/GroupBox.qml b/components/GroupBox.qml
index 8cea42d3..6837ab1f 100644
--- a/components/GroupBox.qml
+++ b/components/GroupBox.qml
@@ -4,9 +4,8 @@ import QtDesktop 0.1
Components.GroupBox {
id: groupbox
- width: Math.max(200, contentWidth + sizeHint.width)
- height: contentHeight + sizeHint.height + 4
- property variant sizeHint: backgroundItem.sizeFromContents(0, 24)
+ implicitWidth: Math.max(200, contentWidth + backgroundItem.implicitWidth)
+ implicitHeight: contentHeight + backgroundItem.implicitHeight + 4
property bool flat: false
background : StyleItem {
id: styleitem
@@ -15,8 +14,9 @@ Components.GroupBox {
text: groupbox.title
hover: checkbox.containsMouse
on: checkbox.checked
- focus: checkbox.activeFocus
+ hasFocus: checkbox.activeFocus
activeControl: checkable ? "checkbox" : ""
sunken: !flat
+ contentHeight: (title.length > 0 || checkable) ? 24 : 4
}
}
diff --git a/components/Label.qml b/components/Label.qml
new file mode 100644
index 00000000..fe1e3769
--- /dev/null
+++ b/components/Label.qml
@@ -0,0 +1,8 @@
+import QtQuick 1.1
+
+Text {
+ id: label
+ font.pixelSize: 11
+ color: pal.text
+ SystemPalette {id:pal}
+}
diff --git a/components/MenuItem.qml b/components/MenuItem.qml
index 0c8bbc24..15abc4dc 100644
--- a/components/MenuItem.qml
+++ b/components/MenuItem.qml
@@ -1,7 +1,8 @@
-import QtQuick 1.0
+import QtQuick 1.1
Item {
property string text
+ property string iconName
signal hovered
signal selected
}
diff --git a/components/ProgressBar.qml b/components/ProgressBar.qml
index 0ee764a8..822c13f9 100644
--- a/components/ProgressBar.qml
+++ b/components/ProgressBar.qml
@@ -5,12 +5,12 @@ import QtDesktop 0.1
Components.ProgressBar {
id:progressbar
- property variant sizehint: backgroundItem.sizeFromContents(23, 23)
property int orientation: Qt.Horizontal
- property string hint
+ property string styleHint
+
+ implicitWidth: orientation === Qt.Horizontal ? 200 : backgroundItem.implicitHeight
+ implicitHeight: orientation === Qt.Horizontal ? backgroundItem.implicitHeight : 200
- height: orientation === Qt.Horizontal ? sizehint.height : 200
- width: orientation === Qt.Horizontal ? 200 : sizehint.height
SystemPalette {id: syspal}
@@ -25,7 +25,9 @@ Components.ProgressBar {
maximum: indeterminate ? 0 : progressbar.maximumValue * factor
enabled: progressbar.enabled
horizontal: progressbar.orientation == Qt.Horizontal
- hint: progressbar.hint
+ hint: progressbar.styleHint
+ contentWidth: 23
+ contentHeight: 23
}
}
diff --git a/components/RadioButton.qml b/components/RadioButton.qml
index 7909e61d..56a2d227 100644
--- a/components/RadioButton.qml
+++ b/components/RadioButton.qml
@@ -5,22 +5,34 @@ import QtDesktop 0.1
// jb : Size should not depend on background, we should make it consistent
Components.CheckBox {
- id:radiobutton
+ id: radiobutton
property string text
- property string hint
- width:110
- height:20
+ property string styleHint
+
+ implicitWidth: Math.max(120, backgroundItem.implicitWidth)
+ implicitHeight: backgroundItem.implicitHeight
background: StyleItem {
- elementType:"radiobutton"
- sunken:pressed
- on:checked || pressed
- hover:containsMouse
- text:radiobutton.text
- enabled:radiobutton.enabled
- focus:radiobutton.focus
- hint:radiobutton.hint
+ elementType: "radiobutton"
+ sunken: pressed
+ on: checked || pressed
+ hover: containsMouse
+ enabled: radiobutton.enabled
+ hasFocus: radiobutton.activeFocus
+ hint: radiobutton.styleHint
+ contentHeight: textitem.implicitHeight
+ contentWidth: textitem.implicitWidth + indicatorWidth
+ property int indicatorWidth: pixelMetric("indicatorwidth") + 2
+ Text {
+ id: textitem
+ text: radiobutton.text
+ anchors.left: parent.left
+ anchors.leftMargin: parent.indicatorWidth
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ elide: Text.ElideRight
+ }
}
- Keys.onSpacePressed:clicked()
+ Keys.onSpacePressed: {clicked(); checked = !checked; }
}
diff --git a/components/ScrollArea.qml b/components/ScrollArea.qml
index 3e61018d..53421729 100644
--- a/components/ScrollArea.qml
+++ b/components/ScrollArea.qml
@@ -1,46 +1,32 @@
import QtQuick 2.0
import "custom" as Components
+import "private" as Private
import QtDesktop 0.1
FocusScope {
- id: scrollarea
+ id: root
width: 100
height: 100
- property int frameWidth: frame ? styleitem.pixelMetric("defaultframewidth") : 0;
- property int contentHeight : content.childrenRect.height
- property int contentWidth: content.childrenRect.width
- property alias color: colorRect.color
+ // Cosmetic propeties
property bool frame: true
- property bool highlightOnFocus: false
property bool frameAroundContents: styleitem.styleHint("framearoundcontents")
- property alias verticalValue: vscrollbar.value
- property alias horizontalValue: hscrollbar.value
-
- property alias horizontalScrollBar: hscrollbar
- property alias verticalScrollBar: vscrollbar
-
- property int viewportHeight: height - (hscrollbar.visible ? hscrollbar.height : 0) - 2 * frameWidth
- property int viewportWidth: width - (vscrollbar.visible ? vscrollbar.width : 0) - 2 * frameWidth
- property bool blockUpdates: false
+ property bool highlightOnFocus: false
+ property alias color: colorRect.color // background color
+ property int frameWidth: frame ? styleitem.frameWidth : 0
- default property alias data: content.data
+ // Item properties
+ property alias horizontalScrollBar: scroller.horizontalScrollBar
+ property alias verticalScrollBar: scroller.verticalScrollBar
- property int contentY
+ // Viewport properties
property int contentX
-
- onContentYChanged: {
- blockUpdates = true
- vscrollbar.value = contentY
- wheelarea.verticalValue = contentY
- blockUpdates = false
- }
- onContentXChanged: {
- blockUpdates = true
- hscrollbar.value = contentX
- wheelarea.horizontalValue = contentX
- blockUpdates = false
- }
+ property int contentY
+ property int contentHeight : content.childrenRect.height
+ property int contentWidth: content.childrenRect.width
+ property int viewportHeight: height - (horizontalScrollBar.visible ? verticalScrollBar.height : 0) - 2 * frameWidth
+ property int viewportWidth: width - (verticalScrollBar.visible ? verticalScrollBar.width : 0) - 2 * frameWidth
+ default property alias data: content.data
Rectangle {
id: colorRect
@@ -52,109 +38,58 @@ FocusScope {
StyleItem {
id: styleitem
elementType: "frame"
- onElementTypeChanged: scrollarea.frameWidth = styleitem.pixelMetric("defaultframewidth");
sunken: true
visible: frame
anchors.fill: parent
- anchors.rightMargin: frame ? (frameAroundContents ? (vscrollbar.visible ? vscrollbar.width + 2 * frameMargins : 0) : -frameWidth) : 0
- anchors.bottomMargin: frame ? (frameAroundContents ? (hscrollbar.visible ? hscrollbar.height + 2 * frameMargins : 0) : -frameWidth) : 0
- anchors.topMargin: frame ? (frameAroundContents ? 0 : -frameWidth) : 0
+ anchors.rightMargin: frame ? (frameAroundContents ? (verticalScrollBar.visible ? verticalScrollBar.width + 2 * frameMargins : 0) : 0) : 0
+ anchors.bottomMargin: frame ? (frameAroundContents ? (horizontalScrollBar.visible ? horizontalScrollBar.height + 2 * frameMargins : 0) : 0) : 0
+ anchors.topMargin: frame ? (frameAroundContents ? 0 : 0) : 0
+ property int frameWidth
property int scrollbarspacing: styleitem.pixelMetric("scrollbarspacing");
property int frameMargins : frame ? scrollbarspacing : 0
- property int frameoffset: style === "mac" ? -1 : 0
+ Component.onCompleted: frameWidth = styleitem.pixelMetric("defaultframewidth");
+ }
+
+ onContentYChanged: {
+ scroller.blockUpdates = true
+ verticalScrollBar.value = contentY
+ scroller.verticalValue = contentY
+ scroller.blockUpdates = false
+ }
+
+ onContentXChanged: {
+ scroller.blockUpdates = true
+ horizontalScrollBar.value = contentX
+ scroller.horizontalValue = contentX
+ scroller.blockUpdates = false
}
Item {
- id: flickable
+ id: clipper
anchors.fill: styleitem
anchors.margins: frameWidth
clip: true
-
Item {
id: content
- x: -scrollarea.contentX
- y: -scrollarea.contentY
+ x: -root.contentX
+ y: -root.contentY
}
}
- WheelArea {
- id: wheelarea
- anchors.fill: parent
- horizontalMinimumValue: hscrollbar.minimumValue
- horizontalMaximumValue: hscrollbar.maximumValue
- verticalMinimumValue: vscrollbar.minimumValue
- verticalMaximumValue: vscrollbar.maximumValue
-
- onVerticalValueChanged: {
- if (!blockUpdates)
- contentY = verticalValue
- }
- onHorizontalValueChanged: {
- if (!blockUpdates)
- contentX = horizontalValue
- }
- }
-
- ScrollBar {
- id: hscrollbar
- orientation: Qt.Horizontal
- property int availableWidth : scrollarea.width - (vscrollbar.visible ? vscrollbar.width : 0)
- visible: contentWidth > availableWidth
- maximumValue: contentWidth > availableWidth ? scrollarea.contentWidth - availableWidth: 0
- minimumValue: 0
- anchors.bottom: parent.bottom
- anchors.bottomMargin: styleitem.frameoffset
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.leftMargin: (frame ? frameWidth : 0)
- anchors.rightMargin: { vscrollbar.visible ? scrollbarExtent : (frame ? 1 : 0) }
- property int scrollbarExtent : styleitem.pixelMetric("scrollbarExtent");
- onValueChanged: {
- if (!blockUpdates)
- contentX = value
- }
- }
-
- ScrollBar {
- id: vscrollbar
- orientation: Qt.Vertical
- property int availableHeight : scrollarea.height - (hscrollbar.visible ? (hscrollbar.height) : 0)
- visible: contentHeight > availableHeight
- maximumValue: contentHeight > availableHeight ? scrollarea.contentHeight - availableHeight : 0
- minimumValue: 0
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.topMargin: styleitem.style == "mac" ? 1 : 0
- anchors.rightMargin: styleitem.frameoffset
- anchors.bottomMargin: hscrollbar.visible ? hscrollbar.height : styleitem.frameoffset
- onValueChanged: {
- if (!blockUpdates)
- contentY = value
- }
- }
-
- Rectangle {
- // This is the filled corner between scrollbars
- id: cornerFill
- anchors.left: vscrollbar.left
- anchors.right: vscrollbar.right
- anchors.top: hscrollbar.top
- anchors.bottom: hscrollbar.bottom
- visible: hscrollbar.visible && vscrollbar.visible
- SystemPalette { id: syspal }
- color: syspal.window
+ Private.ScrollAreaHelper {
+ id: scroller
+ anchors.fill: parent
}
StyleItem {
z: 2
anchors.fill: parent
- anchors.topMargin: -4
+ anchors.topMargin: -3
anchors.leftMargin: -3
anchors.rightMargin: -5
- anchors.bottomMargin: -6
+ anchors.bottomMargin: -5
visible: highlightOnFocus && parent.activeFocus && styleitem.styleHint("focuswidget")
elementType: "focusframe"
diff --git a/components/ScrollBar.qml b/components/ScrollBar.qml
index c7de2270..1fa0aa17 100644
--- a/components/ScrollBar.qml
+++ b/components/ScrollBar.qml
@@ -13,8 +13,8 @@ Item {
property alias value: slider.value
property bool scrollToClickposition: styleitem.styleHint("scrollToClickPosition")
- width: orientation == Qt.Horizontal ? 200 : internal.scrollbarExtent
- height: orientation == Qt.Horizontal ? internal.scrollbarExtent : 200
+ implicitWidth: orientation == Qt.Horizontal ? 200 : internal.scrollbarExtent
+ implicitHeight: orientation == Qt.Horizontal ? internal.scrollbarExtent : 200
onValueChanged: internal.updateHandle()
@@ -163,4 +163,5 @@ Item {
positionAtMaximum: internal.grooveSize
}
}
+
}
diff --git a/components/Slider.qml b/components/Slider.qml
index 65f971cc..0994f7c2 100644
--- a/components/Slider.qml
+++ b/components/Slider.qml
@@ -7,17 +7,22 @@ import QtDesktop 0.1
Components.Slider{
id: slider
- property bool tickmarksEnabled: true
+ property bool tickmarksEnabled: false
property string tickPosition: "Below" // "Above", "Below", "BothSides"
- StyleItem { id:buttonitem; elementType: "slider" }
+ StyleItem {
+ id:buttonitem
+ elementType: "slider"
+ contentWidth:23
+ contentHeight:23
+ }
- property variant sizehint: buttonitem.sizeFromContents(23, 23)
property int orientation: Qt.Horizontal
- height: orientation === Qt.Horizontal ? sizehint.height : 200
- width: orientation === Qt.Horizontal ? 200 : sizehint.height
- property string hint;
+ implicitWidth: orientation === Qt.Horizontal ? 200 : buttonitem.implicitHeight
+ implicitHeight: orientation === Qt.Horizontal ? buttonitem.implicitHeight : 200
+
+ property string styleHint;
groove: StyleItem {
anchors.fill:parent
@@ -29,8 +34,8 @@ Components.Slider{
value: slider.value*100
horizontal: slider.orientation == Qt.Horizontal
enabled: slider.enabled
- focus: slider.focus
- hint: slider.hint
+ hasFocus: slider.focus
+ hint: slider.styleHint
activeControl: tickmarksEnabled ? tickPosition.toLowerCase() : ""
}
diff --git a/components/SpinBox.qml b/components/SpinBox.qml
index 9b476fde..4e6e84b7 100644
--- a/components/SpinBox.qml
+++ b/components/SpinBox.qml
@@ -8,21 +8,26 @@ Components.SpinBox {
property variant __upRect;
property variant __downRect;
property int __margin: (height -16)/2
- property string hint
+ property string styleHint
// Align height with button
- topMargin:__margin
- bottomMargin:__margin
+ topMargin: __margin
+ bottomMargin: __margin
leftMargin:6
rightMargin:6
- StyleItem { id:edititem ; elementType:"edit" ; visible:false }
- property int buttonHeight: edititem.sizeFromContents(70, 20).height
- property int buttonWidth: edititem.sizeFromContents(70, 20).width
+ StyleItem {
+ id:edititem
+ elementType: "edit"
+ visible: false
+ contentWidth: 70
+ contentHeight: 20
+ }
+
+ implicitWidth: edititem.implicitWidth
+ implicitHeight: edititem.implicitHeight
- height: buttonHeight
- width: buttonWidth
clip:false
background: Item {
@@ -70,13 +75,13 @@ Components.SpinBox {
elementType: "spinbox"
sunken: (downEnabled && downPressed) | (upEnabled && upPressed)
hover: containsMouse
- focus: spinbox.focus
+ hasFocus: spinbox.focus
enabled: spinbox.enabled
value: (upPressed ? 1 : 0) |
(downPressed == 1 ? 1<<1 : 0) |
(upEnabled ? (1<<2) : 0) |
(downEnabled == 1 ? (1<<3) : 0)
- hint: spinbox.hint
+ hint: spinbox.styleHint
}
}
diff --git a/components/SplitterColumn.qml b/components/SplitterColumn.qml
new file mode 100644
index 00000000..de6dd25d
--- /dev/null
+++ b/components/SplitterColumn.qml
@@ -0,0 +1,123 @@
+import QtQuick 1.1
+import "custom" as Components
+
+/*
+*
+* SplitterColumn
+*
+* SplitterColumn is a component that provides a way to layout items horisontally with
+* a draggable splitter added in-between each item.
+*
+* Add items to the SplitterColumn by inserting them as child items. The splitter handle
+* is outsourced as a delegate (handleBackground). To enable the user to drag the handle,
+* it will need to contain a mouse area that communicates with the SplitterColumn by binding
+* 'drag.target: handle'. The 'handle' property points to the handle item that embedds
+* the delegate. To change handle positions, either change 'y; (or 'height') of 'handle', or
+* change the height of the child items inside the SplitterColumn. If you set the visibility
+* of a child item to false, the corresponding handle will also be hidden, and the
+* SplitterColumn will perform a layout update to fill up available space.
+*
+* There will always be one (and only one) item in the SplitterColumn that is 'expanding'.
+* The expanding item is the child that will get all the remaining space in the SplitterColumn
+* (down to its own mimimumHeight/Height) when all other items have been layed out.
+* This means that that 'height', 'percentageHeight' and 'maximumHeight' will be ignored for this item.
+* By default, the last visible child item of the SplitterColumn will be 'expanding'.
+*
+* A handle can belong to the item on the left side, or the right side, of the handle. Which one depends
+* on the expaning item. If the expanding item is to the right of the handle, the
+* handle will belong to the item on the left. If it is to the left, it will belong to the item on the
+* right. This will again control which item that gets resized when the user drags a handle, and which
+* handle that gets hidden when an item is told to hide.
+*
+* NB: Since SplitterColumn might modify geometry properties like 'height' and 'y; of child items
+* to e.g. ensure they stay within minimumHeight/maximumHeight, explicit expression bindings
+* to such properties can easily be broken up by the SplitterColumn, and is not recommended.
+*
+* The SplitterColumn contains the following API:
+*
+* Component handleBackground - delegate that will be instanciated between each
+* child item. Inside the delegate, the following properties are available:
+* int handleIndex - specifies the index of the splitter handle. The handle
+* between the first and the second item will get index 0, the next handle index 1 etc.
+* Item handle - convenience property that points to the item where the handle background is
+* instanciated as a child. Identical to splitterColumn.handles[handleIndex]. The handle
+* background iteself can be accessed through handle.item.
+* Modify 'handle[d.offset]' to move the handle (or change 'height' of SplitterColumn child items).
+* Item splitterItem - convenience property that points to the child item that the handle controls.
+* Also refer to information about the expanding item above.
+* Item splitterColumn - points to the SplitterColumn that the handle is in.
+* List<Item> items - contains the list of child items in the SplitterColumn. Currently read-only.
+* List<Item> handles - contains the list of splitter handles in the SplitterColumn. Note that this list will
+* be populated after all child items has completed, so accessing it from Component.onCompleted
+* inside a SplitterColumn child item will not work. To get to the handle background, access the
+* 'background' property of the handle, e.g. handles[0].background. Read-only.
+* real preferredHeight/Height - contains the accumulated with of all child items and handles, except
+* the expanding item. If the expanding item has a minimum height, the minimum height will
+* be included.
+*
+* The following attached properties can be used for each child item of SplitterColumn:
+*
+* real Splitter.minimumSize - ensures that the item cannot be resized below the
+* given pixelvalue. A value of -1 will disable it.
+* real Splitter.maximumSize - ensures that the item cannot be resized above the
+* given pixelvalue. A value of -1 will disable it.
+* real percentageHeight - This value specifies a percentage (0 - 100) of the height of the
+* SplitterColumn height. If the height of the SplitterColumn change, the height of the item will
+* change as well. 'percentageHeight' have precedence over 'height', which means that
+* SplitterColumn will ignore any assignments to 'height'. A value of -1 disables it.
+* bool Splitter.expanding - See explanation of 'expanding' above. If set to true, the current item
+* will be the expanding item in the SplitterColumn. If set to false, the SplitterColumn will
+* autmatically choose the last visible child of the SplitterColumn as expanding instead.
+* int Splitter.itemIndex - will be assigned a read-only value with the item index. Can be used to e.g. look-up
+* the handles sourrounding the item (parent.handles[itemIndex])
+*
+* Example:
+*
+* To create a SplitterColumn with three items, and let
+* the center item be the one that should be expanding, one
+* could do the following:
+*
+* SplitterColumn {
+* anchors.fill: parent
+*
+* Rectangle {
+* Splitter.maximumSize: 400
+* color: "gray"
+* height: 200
+* }
+* Rectangle {
+* Splitter.minimumSize: 50
+* Splitter.expanding: true
+* color: "darkgray"
+* }
+* Rectangle {
+* color: "gray"
+* height: 200
+* }
+* }
+*/
+
+Components.Splitter {
+ orientation: Qt.Vertical
+ handleBackground: StyleItem {
+ id: styleitem
+ elementType: "splitter"
+ height: handleWidth != -1 ? handleWidth : pixelMetric("splitterwidth")
+ horizontal: false
+ property alias pressed: mouseArea.pressed
+ property bool dragged: mouseArea.drag.active
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ anchors.topMargin: (parent.height <= 1) ? -2 : 0
+ anchors.bottomMargin: (parent.height <= 1) ? -2 : 0
+ drag.axis: Qt.XandYAxis // Why doesn't X-axis work?
+ drag.target: handle
+ CursorArea {
+ anchors.fill: parent
+ cursor: CursorArea.SplitVCursor
+ }
+ }
+ }
+}
diff --git a/components/SplitterRow.qml b/components/SplitterRow.qml
index c6012e4c..eb0fd17f 100644
--- a/components/SplitterRow.qml
+++ b/components/SplitterRow.qml
@@ -2,26 +2,124 @@ import QtQuick 1.1
import "custom" as Components
import QtDesktop 0.1
-Components.SplitterRow {
+/*
+*
+* SplitterRow
+*
+* SplitterRow is a component that provides a way to layout items horisontally with
+* a draggable splitter added in-between each item.
+*
+* Add items to the SplitterRow by inserting them as child items. The splitter handle
+* is outsourced as a delegate (handleBackground). To enable the user to drag the handle,
+* it will need to contain a mouse area that communicates with the SplitterRow by binding
+* 'drag.target: handle'. The 'handle' property points to the handle item that embedds
+* the delegate. To change handle positions, either change 'x' (or 'width') of 'handle', or
+* change the width of the child items inside the SplitterRow. If you set the visibility
+* of a child item to false, the corresponding handle will also be hidden, and the
+* SplitterRow will perform a layout update to fill up available space.
+*
+* There will always be one (and only one) item in the SplitterRow that is 'expanding'.
+* The expanding item is the child that will get all the remaining space in the SplitterRow
+* (down to its own mimimumWidth/Height) when all other items have been layed out.
+* This means that that 'width', 'percentageWidth' and 'maximumWidth' will be ignored for this item.
+* By default, the last visible child item of the SplitterRow will be 'expanding'.
+*
+* A handle can belong to the item on the left side, or the right side, of the handle. Which one depends
+* on the expaning item. If the expanding item is to the right of the handle, the
+* handle will belong to the item on the left. If it is to the left, it will belong to the item on the
+* right. This will again control which item that gets resized when the user drags a handle, and which
+* handle that gets hidden when an item is told to hide.
+*
+* NB: Since SplitterRow might modify geometry properties like 'width' and 'x' of child items
+* to e.g. ensure they stay within minimumWidth/maximumWidth, explicit expression bindings
+* to such properties can easily be broken up by the SplitterRow, and is not recommended.
+*
+* The SplitterRow contains the following API:
+*
+* Component handleBackground - delegate that will be instanciated between each
+* child item. Inside the delegate, the following properties are available:
+* int handleIndex - specifies the index of the splitter handle. The handle
+* between the first and the second item will get index 0, the next handle index 1 etc.
+* Item handle - convenience property that points to the item where the handle background is
+* instanciated as a child. Identical to splitterRow.handles[handleIndex]. The handle
+* background iteself can be accessed through handle.item.
+* Modify 'handle[d.offset]' to move the handle (or change 'width' of SplitterRow child items).
+* Item splitterItem - convenience property that points to the child item that the handle controls.
+* Also refer to information about the expanding item above.
+* Item splitterRow - points to the SplitterRow that the handle is in.
+* List<Item> items - contains the list of child items in the SplitterRow. Currently read-only.
+* List<Item> handles - contains the list of splitter handles in the SplitterRow. Note that this list will
+* be populated after all child items has completed, so accessing it from Component.onCompleted
+* inside a SplitterRow child item will not work. To get to the handle background, access the
+* 'background' property of the handle, e.g. handles[0].background. Read-only.
+* real preferredWidth/Height - contains the accumulated with of all child items and handles, except
+* the expanding item. If the expanding item has a minimum width, the minimum width will
+* be included.
+*
+* The following attached properties can optionally be used for each child item of SplitterRow:
+*
+* real Splitter.minimumSize - ensures that the item cannot be resized below the
+* given pixelvalue. A value of -1 will disable it.
+* real Splitter.maximumSixe - ensures that the item cannot be resized above the
+* given value. A value of -1 will disable it.
+* real Splitter.percentageSize - This value specifies a percentage (0 - 100) of the width of the
+* SplitterRow width. If the width of the SplitterRow change, the width of the item will
+* change as well. 'percentageWidth' have precedence over 'width', which means that
+* SplitterRow will ignore any assignments to 'width'. A value of -1 disables it.
+* bool Splitter.expanding - See explanation of 'expanding' above. If set to true, the current item
+* will be the expanding item in the SplitterRow. If set to false, the SplitterRow will
+* autmatically choose the last visible child of the SplitterRow as expanding instead.
+* int Splitter.itemIndex - will be assigned a read-only value with the item index. Can be used to e.g. look-up
+* the handles sourrounding the item (parent.handles[itemIndex])
+*
+* Example:
+*
+* To create a SplitterRow with three items, and let
+* the center item be the one that should be expanding, one
+* could do the following:
+*
+* SplitterRow {
+* anchors.fill: parent
+*
+* Rectangle {
+* Splitter.maximumWidth: 400
+* color: "gray"
+* width: 200
+* }
+* Rectangle {
+* Splitter.minimumWidth: 50
+* Splitter.expanding: true
+* color: "darkgray"
+* }
+* Rectangle {
+* color: "gray"
+* width: 200
+* }
+* }
+*/
+
+
+Components.Splitter {
+ orientation: Qt.Horizontal
handleBackground: StyleItem {
- id: styleitem
- elementType: "splitter"
- width: pixelMetric("splitterwidth")
- property alias pressed: mouseArea.pressed
- property bool dragged: mouseArea.drag.active
+ id: styleitem
+ elementType: "splitter"
+ width: handleWidth != -1 ? handleWidth : pixelMetric("splitterwidth")
+ property alias pressed: mouseArea.pressed
+ property bool dragged: mouseArea.drag.active
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- anchors.leftMargin: (parent.width <= 1) ? -2 : 0
- anchors.rightMargin: (parent.width <= 1) ? -2 : 0
- drag.axis: Qt.YAxis
- drag.target: handle
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ anchors.leftMargin: (parent.width <= 1) ? -2 : 0
+ anchors.rightMargin: (parent.width <= 1) ? -2 : 0
+ drag.axis: Qt.YAxis
+ drag.target: handle
- StyleItem {
- anchors.fill: parent
- cursor: "splithcursor"
- }
+ CursorArea {
+ anchors.fill: parent
+ cursor: CursorArea.SplitHCursor
}
+ }
}
}
diff --git a/components/StatusBar.qml b/components/StatusBar.qml
new file mode 100644
index 00000000..92bea256
--- /dev/null
+++ b/components/StatusBar.qml
@@ -0,0 +1,12 @@
+import QtQuick 1.1
+import "."
+import "custom" as Components
+
+Item {
+ width: parent ? parent.width : 200
+ height: 24
+ StyleItem {
+ anchors.fill: parent
+ elementType: "statusbar"
+ }
+}
diff --git a/components/Switch.qml b/components/Switch.qml
deleted file mode 100644
index 9031e8ce..00000000
--- a/components/Switch.qml
+++ /dev/null
@@ -1,21 +0,0 @@
-import QtQuick 2.0
-import "custom" as Components
-
-Components.Switch {
- id:widget
- minimumWidth:100
- minimumHeight:30
-
- groove:StyleItem {
- elementType:"edit"
- sunken: true
- }
-
- handle: StyleItem {
- elementType:"button"
- width:widget.width/2
- height:widget.height-4
- hover:containsMouse
- }
-}
-
diff --git a/components/TabBar.qml b/components/TabBar.qml
index 69df6dee..ad70fd9c 100644
--- a/components/TabBar.qml
+++ b/components/TabBar.qml
@@ -48,7 +48,6 @@ Item {
Row {
id: tabrow
- focus: true
property int paintMargins: 1
states:
State {
@@ -69,34 +68,35 @@ Item {
focus:true
property int tabindex: index
property bool selected : tabFrame.current == index
- z: selected ? 1 : -index
+ z: selected ? 1 : -1
+ width: Math.min(implicitWidth, tabbar.width/tabs.length)
function updateRect() {
- var rect = style.sizeFromContents(textitem.width + tabHSpace + 2, Math.max(style.fontHeight + tabVSpace + 6, 0))
- width = rect.width
- height = rect.height
+ implicitWidth = style.implicitWidth
+ height = style.implicitHeight
}
- // Component.onCompleted: print("taboverlap" + tabOverlap + " tabbaseoverlap " + tabBaseOverlap + " overlap " +__overlap + " hspace " + tabHSpace)
StyleItem {
id: style
elementType: "tab"
selected: tab.selected
info: tabbar.position
- text: tabFrame.tabs[index].title
+ text: tabFrame.tabs[index].title
hover: mousearea.containsMouse
- focus: tabbar.focus && selected
+ hasFocus: tabbar.focus && selected
property bool first: index === 0
paintMargins: tabrow.paintMargins
- activeControl: tabFrame.count == 1 ? "only" : index === 0 ? "beginning" :
- index == tabFrame.count-1 ? "end" : "middle"
+ activeControl: tabFrame.count === 1 ? "only" : index === 0 ? "beginning" :
+ index === tabFrame.count-1 ? "end" : "middle"
anchors.fill: parent
anchors.margins: -paintMargins
+ contentWidth: textitem.width + tabHSpace + 2
+ contentHeight: Math.max(style.fontHeight + tabVSpace + 6, 0)
Text {
id: textitem
// Used for size hint
visible: false
onWidthChanged: updateRect()
onHeightChanged: updateRect()
- text: tabFrame.tabs[index].title
+ text: tabFrame.tabs[index].title
}
}
MouseArea {
diff --git a/components/TabFrame.qml b/components/TabFrame.qml
index 43794937..725bec91 100644
--- a/components/TabFrame.qml
+++ b/components/TabFrame.qml
@@ -6,23 +6,16 @@ Item {
id: tabWidget
width: 100
height: 100
- focus: true
- property TabBar tabbar
property int current: 0
property int count: stack.children.length
- property bool frame:true
+ property bool frame: true
property bool tabsVisible: true
property string position: "North"
default property alias tabs : stack.children
+ property Item tabBar: tabbarItem
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 : frameitem.pixelMetric("tabbaseoverlap")// add paintmargins;
function __setOpacities() {
@@ -31,10 +24,18 @@ Item {
}
}
- function addTab(component) {
- var tab = component.createObject(null);
+ Component {
+ id: tabcomp
+ Tab {}
+ }
+
+ function addTab(component, title) {
+ var tab = tabcomp.createObject(this);
+ component.createObject(tab)
tab.parent = stack
- current = count-1
+ tab.title = title
+ __setOpacities()
+ return tab
}
function removeTab(id) {
@@ -49,9 +50,9 @@ Item {
z: style == "oxygen" ? 1 : 0
elementType: "tabframe"
info: position
- value: tabbar && tabsVisible && tabbar.tab(current) ? tabbar.tab(current).x : 0
- minimum: tabbar && tabsVisible && tabbar.tab(current) ? tabbar.tab(current).width : 0
- maximum: tabbar && tabsVisible ? tabbar.tabWidth : width
+ value: tabbarItem && tabsVisible && tabbarItem.tab(current) ? tabbarItem.tab(current).x : 0
+ minimum: tabbarItem && tabsVisible && tabbarItem.tab(current) ? tabbarItem.tab(current).width : 0
+ maximum: tabbarItem && tabsVisible ? tabbarItem.tabWidth : width
anchors.fill: parent
property int frameWidth: pixelMetric("defaultframewidth")
@@ -64,27 +65,34 @@ Item {
anchors.bottomMargin: anchors.margins + (frameitem.style =="mac" ? 6 : 0)
}
- anchors.topMargin: tabbar && tabsVisible && position == "North" ? tabbar.height - __baseOverlap : 0
+ anchors.topMargin: tabbarItem && tabsVisible && position == "North" ? Math.max(0, tabbarItem.height - __baseOverlap) : 0
states: [
State {
name: "South"
- when: position == "South" && tabbar!= undefined
+ when: position == "South" && tabbarItem!= undefined
PropertyChanges {
target: frameitem
anchors.topMargin: 0
- anchors.bottomMargin: tabbar ? tabbar.height - __baseOverlap: 0
+ anchors.bottomMargin: tabbarItem ? tabbarItem.height - __baseOverlap: 0
}
PropertyChanges {
- target: tabbar
+ target: tabbarItem
anchors.topMargin: -__baseOverlap
}
AnchorChanges {
- target: tabbar
+ target: tabbarItem
anchors.top: frameitem.bottom
anchors.bottom: undefined
}
}
]
}
+ TabBar {
+ id: tabbarItem
+ tabFrame: tabWidget
+ anchors.top: tabWidget.top
+ anchors.left: tabWidget.left
+ anchors.right: tabWidget.right
+ }
}
diff --git a/components/TableColumn.qml b/components/TableColumn.qml
index 5142a962..42fb12e4 100644
--- a/components/TableColumn.qml
+++ b/components/TableColumn.qml
@@ -1,9 +1,12 @@
import QtQuick 2.0
QtObject {
- property string caption
- property string property
+ property string title
+ property string role
property int width: 160
+ property int x
property bool visible: true
property int elideMode: Text.ElideRight
+ property int textAlignment: Text.AlignLeft
+ property Component delegate
}
diff --git a/components/TableView.qml b/components/TableView.qml
index b813e2ab..257f370f 100644
--- a/components/TableView.qml
+++ b/components/TableView.qml
@@ -1,5 +1,6 @@
import QtQuick 2.0
import QtDesktop 0.1
+import "private" as Private
/*
*
@@ -41,8 +42,8 @@ import QtDesktop 0.1
* by setting the default header property :
*
* TableView {
-* TableColumn{ property: "column1" ; caption: "Column 1" ; width:100}
-* TableColumn{ property: "column2" ; caption: "Column 2" ; width:200}
+* TableColumn{ role: "column1" ; title: "Column 1" ; width:100}
+* TableColumn{ role: "column2" ; title: "Column 2" ; width:200}
* model: datamodel
* }
*
@@ -62,45 +63,65 @@ import QtDesktop 0.1
FocusScope{
id: root
+
property variant model
- property int frameWidth: frame ? styleitem.pixelMetric("defaultframewidth") : 0;
- property alias contentHeight : tree.contentHeight
- property alias contentWidth: tree.contentWidth
- property bool frame: true
- property bool highlightOnFocus: false
- property bool frameAroundContents: styleitem.styleHint("framearoundcontents")
- property int sortColumn // Index of currently selected sort column
- property bool sortIndicatorVisible: false // enables or disables sort indicator
- property string sortIndicatorDirection: "down" // "up" or "down" depending on current state
+ // Framewidth seems to be 1 regardless of style
+ property int frameWidth: frame ? frameitem.frameWidth : 0;
+ width: 200
+ height: 200
+ // Cosmetic properties
+ property bool frame: true
+ property bool frameAroundContents: styleitem.styleHint("framearoundcontents")
+ property bool highlightOnFocus: false
property bool alternateRowColor: true
- property alias contentX: tree.contentX
- property alias contentY: tree.contentY
-
- property alias currentIndex: tree.currentIndex // Should this be currentRowIndex?
-
- property int headerHeight: headerrow.height
+ property bool headerVisible: true
+ // Styling properties
property Component itemDelegate: standardDelegate
property Component rowDelegate: rowDelegate
property Component headerDelegate: headerDelegate
- property alias cacheBuffer: tree.cacheBuffer
+ property color backgroundColor: "white"
- property bool headerVisible: true
+ // Sort properties
+ property int sortColumn // Index of currently selected sort column
+ property bool sortIndicatorVisible: false // enables or disables sort indicator
+ property string sortIndicatorDirection: "down" // "up" or "down" depending on current state
+ // Item properties
default property alias header: tree.header
+ property alias horizontalScrollBar: scroller.horizontalScrollBar
+ property alias verticalScrollBar: scroller.verticalScrollBar
+ // Viewport properties
+ property alias contentX: tree.contentX
+ property alias contentY: tree.contentY
+ property alias contentHeight : tree.contentHeight
+ property alias contentWidth: tree.contentWidth
+ property alias viewportWidth: scroller.availableWidth
+ property alias viewportHeight: scroller.availableHeight
+ property alias count: tree.count
+
+ property alias cacheBuffer: tree.cacheBuffer
+ property alias currentIndex: tree.currentIndex // Should this be currentRowIndex?
+
+ // Signals
signal activated
Component {
id: standardDelegate
Item {
+ height: Math.max(16, styleitem.implicitHeight)
property int implicitWidth: sizehint.paintedWidth + 4
Text {
+ id: label
width: parent.width
- anchors.margins: 4
+ anchors.margins: 6
+ font.pointSize: itemstyle.fontPointSize
anchors.left: parent.left
+ anchors.right: parent.right
+ horizontalAlignment: itemTextAlignment
anchors.verticalCenter: parent.verticalCenter
elide: itemElideMode
text: itemValue ? itemValue : ""
@@ -108,12 +129,19 @@ FocusScope{
}
Text {
id: sizehint
+ font: label.font
text: itemValue ? itemValue : ""
- visible:false
+ visible: false
}
}
}
+ StyleItem {
+ id: itemstyle
+ elementType: "item"
+ visible:false
+ }
+
Component {
id: nativeDelegate
// This gives more native styling, but might be less performant
@@ -133,6 +161,7 @@ FocusScope{
sunken: itemPressed
text: itemValue
hover: itemContainsMouse
+ info: itemPosition
}
}
@@ -148,23 +177,25 @@ FocusScope{
Rectangle {
id: colorRect
- color: "white"
+ color: backgroundColor
anchors.fill: frameitem
anchors.margins: frameWidth
- anchors.rightMargin: (!frameAroundContents && vscrollbar.visible ? vscrollbar.width : 0) + frameWidth
- anchors.bottomMargin: (!frameAroundContents && hscrollbar.visible ? hscrollbar.height : 0) +frameWidth
+ anchors.rightMargin: (!frameAroundContents && verticalScrollBar.visible ? verticalScrollBar.width : 0) + frameWidth
+ anchors.bottomMargin: (!frameAroundContents && horizontalScrollBar.visible ? horizontalScrollBar.height : 0) +frameWidth
}
StyleItem {
id: frameitem
elementType: "frame"
- onElementTypeChanged: scrollarea.frameWidth = styleitem.pixelMetric("defaultframewidth");
+ Component.onCompleted: frameWidth = styleitem.pixelMetric("defaultframewidth");
sunken: true
visible: frame
anchors.fill: parent
- anchors.rightMargin: frame ? (frameAroundContents ? (vscrollbar.visible ? vscrollbar.width + 2 * frameMargins : 0) : -frameWidth) : 0
- anchors.bottomMargin: frame ? (frameAroundContents ? (hscrollbar.visible ? hscrollbar.height + 2 * frameMargins : 0) : -frameWidth) : 0
- anchors.topMargin: frame ? (frameAroundContents ? 0 : -frameWidth) : 0
+ anchors.rightMargin: frame ? (frameAroundContents ? (verticalScrollBar.visible ? verticalScrollBar.width + 2 * frameMargins : 0) : 0) : 0
+ anchors.bottomMargin: frame ? (frameAroundContents ? (horizontalScrollBar.visible ? horizontalScrollBar.height + 2 * frameMargins : 0) : 0) : 0
+ anchors.topMargin: frame ? frameAroundContents : 0
+ anchors.leftMargin: frame ? frameAroundContents : 0
+ property int frameWidth
property int scrollbarspacing: styleitem.pixelMetric("scrollbarspacing");
property int frameMargins : frame ? scrollbarspacing : 0
}
@@ -182,27 +213,28 @@ FocusScope{
}
// Handle vertical scrolling whem dragging mouse outside boundraries
-
- Timer { running: mousearea.autoincrement; repeat: true; interval: 20 ; onTriggered: incrementCurrentIndex()}
- Timer { running: mousearea.autodecrement; repeat: true; interval: 20 ; onTriggered: decrementCurrentIndex()}
+ Timer { running: mousearea.autoincrement && verticalScrollBar.visible; repeat: true; interval: 20 ; onTriggered: incrementCurrentIndex()}
+ Timer { running: mousearea.autodecrement && verticalScrollBar.visible; repeat: true; interval: 20 ; onTriggered: decrementCurrentIndex()}
onPositionChanged: {
if (mouseY > tree.height && pressed) {
- if (autoincrement)return
- autodecrement = false
- autoincrement = true
+ if (autoincrement) return;
+ autodecrement = false;
+ autoincrement = true;
} else if (mouseY < 0 && pressed) {
- if (autodecrement)return
- autoincrement = false
- autodecrement = true
+ if (autodecrement) return;
+ autoincrement = false;
+ autodecrement = true;
} else {
- autoincrement = false
- autodecrement = false
+ autoincrement = false;
+ autodecrement = false;
}
- var y = Math.min(contentY + tree.height - 5, Math.max(mouseY + contentY, contentY))
- var newIndex = tree.indexAt(0, y)
- tree.currentIndex = tree.indexAt(0, y)
+ var y = Math.min(contentY + tree.height - 5, Math.max(mouseY + contentY, contentY));
+ var newIndex = tree.indexAt(0, y);
+ if (newIndex >= 0)
+ tree.currentIndex = tree.indexAt(0, y);
}
+
onPressed: {
tree.forceActiveFocus()
var x = Math.min(contentWidth - 5, Math.max(mouseX + contentX, 0))
@@ -216,56 +248,82 @@ FocusScope{
}
function decrementCurrentIndex() {
- tree.blockUpdates = true;
+ scroller.blockUpdates = true;
tree.decrementCurrentIndex();
- wheelarea.verticalValue = contentY/wheelarea.scale;
- tree.blockUpdates = false;
+ scroller.verticalValue = contentY;
+ scroller.blockUpdates = false;
}
function incrementCurrentIndex() {
- tree.blockUpdates = true;
+ scroller.blockUpdates = true;
tree.incrementCurrentIndex();
- wheelarea.verticalValue = contentY/wheelarea.scale;
- tree.blockUpdates = false;
+ scroller.verticalValue = contentY;
+ scroller.blockUpdates = false;
}
ListView {
id: tree
+
property list<TableColumn> header
- property bool blockUpdates: false
highlightFollowsCurrentItem: true
model: root.model
-
interactive: false
+
anchors.top: tableColumn.bottom
- anchors.topMargin: -frameWidth
anchors.left: frameitem.left
anchors.right: frameitem.right
anchors.bottom: frameitem.bottom
anchors.margins: frameWidth
-
- anchors.rightMargin: (!frameAroundContents && vscrollbar.visible ? vscrollbar.width: 0) + frameWidth
- anchors.bottomMargin: (!frameAroundContents && hscrollbar.visible ? hscrollbar.height : 0) + frameWidth
+ anchors.topMargin: -frameWidth
+ anchors.rightMargin: (!frameAroundContents && verticalScrollBar.visible ? verticalScrollBar.width: 0) + frameWidth
+ anchors.bottomMargin: (!frameAroundContents && horizontalScrollBar.visible ? horizontalScrollBar.height : 0) + frameWidth
focus: true
clip: true
+ // Fills extra rows with alternate color
+ Column {
+ id: rowfiller
+ property variant rowHeight: Math.max(1, contentHeight / count)
+ property int rowCount: height/rowHeight
+ y: contentHeight
+ width: parent.width
+ visible: contentHeight > 0 && alternateRowColor && !verticalScrollBar.visible
+ height: parent.height - contentHeight
+ Repeater {
+ model: visible ? rowfiller.rowCount : 0
+ StyleItem {
+ id: rowfill
+ elementType: "itemrow"
+ width: rowfiller.width
+ height: rowfiller.rowHeight
+ activeControl: (index + count) % 2 === 1 ? "alternate" : ""
+ }
+ }
+ }
+
Keys.onUpPressed: root.decrementCurrentIndex()
Keys.onDownPressed: root.incrementCurrentIndex()
Keys.onPressed: {
if (event.key == Qt.Key_PageUp) {
- vscrollbar.value = vscrollbar.value - tree.height
+ verticalScrollBar.value = verticalScrollBar.value - tree.height
} else if (event.key == Qt.Key_PageDown)
- vscrollbar.value = vscrollbar.value + tree.height
- }
+ verticalScrollBar.value = verticalScrollBar.value + tree.height
+ }
onContentYChanged: {
- // positionViewAtIndex(currentIndex, ListView.Visible)
- // highlight follows item
- blockUpdates = true
- vscrollbar.value = tree.contentY
- blockUpdates = false
+ scroller.blockUpdates = true
+ scroller.verticalValue = tree.contentY
+ verticalScrollBar.value = tree.contentY
+ scroller.blockUpdates = false
+ }
+
+ onContentXChanged: {
+ scroller.blockUpdates = true
+ scroller.horizontalValue = tree.contentX
+ horizontalScrollBar.value = tree.contentX
+ scroller.blockUpdates = false
}
delegate: Item {
@@ -275,6 +333,7 @@ FocusScope{
anchors.margins: frameWidth
property int rowIndex: model.index
property bool itemAlternateBackground: alternateRowColor && rowIndex % 2 == 1
+ property variant itemModelData: hasOwnProperty("modelData") ? modelData : null
Loader {
id: rowstyle
// row delegate
@@ -298,16 +357,21 @@ FocusScope{
Loader {
id: itemDelegateLoader
visible: header[index].visible
- sourceComponent: itemDelegate
+ sourceComponent: header[index].delegate ? header[index].delegate : itemDelegate
property variant model: tree.model
- property variant itemProperty: header[index].property
+ property variant role: header[index].role
+ property variant modelData: itemModelData
width: header[index].width
- height: item ? item.height : Math.max(16, styleitem.sizeFromContents(16, 16).height)
+ height: item !== undefined ? item.height : Math.max(16, styleitem.implicitHeight)
function getValue() {
- if (hasOwnProperty(header[index].property))
- return this[header[index].property]
+ if (header[index].role.length && hasOwnProperty(header[index].role))
+ return this[header[index].role]
+ else if (modelData && modelData.hasOwnProperty(header[index].role))
+ return modelData[header[index].role]
+ else if (modelData)
+ return modelData
return ""
}
property variant itemValue: getValue()
@@ -316,37 +380,45 @@ FocusScope{
property int rowIndex: rowitem.rowIndex
property int columnIndex: index
property int itemElideMode: header[index].elideMode
+ property int itemTextAlignment: header[index].textAlignment
}
}
onWidthChanged: tree.contentWidth = width
}
}
}
+
+
Text{ id:text }
Item {
id: tableColumn
- clip: true
+
anchors.top: frameitem.top
anchors.left: frameitem.left
anchors.right: frameitem.right
anchors.margins: frameWidth
+
+ clip: true
visible: headerVisible
- Behavior on height { NumberAnimation{duration:80}}
- height: headerVisible ? styleitem.sizeFromContents(text.font.pixelSize, styleitem.fontHeight).height : frameWidth
+ height: headerVisible ? styleitem.implicitHeight : frameWidth
+
+ Behavior on height { NumberAnimation{ duration: 80 } }
Row {
id: headerrow
-
anchors.top: parent.top
height:parent.height
x: -tree.contentX
Repeater {
id: repeater
- model: header.length
+
property int targetIndex: -1
property int dragIndex: -1
+
+ model: header.length
+
delegate: Item {
z:-index
width: header[index].width
@@ -356,10 +428,13 @@ FocusScope{
Loader {
sourceComponent: root.headerDelegate
anchors.fill: parent
- property string itemValue: header[index].caption
+ property string itemValue: header[index].title
property string itemSort: (sortIndicatorVisible && index == sortColumn) ? (sortIndicatorDirection == "up" ? "up" : "down") : "";
property bool itemPressed: headerClickArea.pressed
property bool itemContainsMouse: headerClickArea.containsMouse
+ property string itemPosition: header.length === 1 ? "only" :
+ index===header.length-1 ? "end" :
+ index===0 ? "beginning" : ""
}
Rectangle{
id: targetmark
@@ -368,6 +443,7 @@ FocusScope{
opacity: (index == repeater.targetIndex && repeater.targetIndex != repeater.dragIndex) ? 0.5 : 0
Behavior on opacity { NumberAnimation{duration:160}}
color: palette.highlight
+ SystemPalette{id:palette}
}
MouseArea{
@@ -420,14 +496,16 @@ FocusScope{
Loader {
id: draghandle
- parent: tableColumn
- sourceComponent: root.headerDelegate
- width: header[index].width
- height: parent.height
- property string itemValue: header[index].caption
+ property string itemValue: header[index].title
property string itemSort: (sortIndicatorVisible && index == sortColumn) ? (sortIndicatorDirection == "up" ? "up" : "down") : "";
property bool itemPressed: headerClickArea.pressed
property bool itemContainsMouse: headerClickArea.containsMouse
+ property string itemPosition
+
+ parent: tableColumn
+ width: header[index].width
+ height: parent.height
+ sourceComponent: root.headerDelegate
visible: headerClickArea.pressed
opacity: 0.5
}
@@ -460,9 +538,9 @@ FocusScope{
header[index].width = minWidth
}
onPressedChanged: if(pressed)offset=mouseX
- StyleItem {
+ CursorArea {
anchors.fill: parent
- cursor: "splithcursor"
+ cursor: CursorArea.SplitHCursor
}
}
}
@@ -470,95 +548,28 @@ FocusScope{
}
Loader {
id: loader
- z:-1
- sourceComponent: root.headerDelegate
- anchors.top: parent.top
- anchors.right: parent.right
- anchors.bottom: headerrow.bottom
- anchors.rightMargin: -2
- width: root.width - headerrow.width
property string itemValue
property string itemSort
property bool itemPressed
property bool itemContainsMouse
- }
- }
-
- WheelArea {
- id: wheelarea
- anchors.fill: parent
- property int scale: 5
- horizontalMinimumValue: hscrollbar.minimumValue/scale
- horizontalMaximumValue: hscrollbar.maximumValue/scale
- verticalMinimumValue: vscrollbar.minimumValue/scale
- verticalMaximumValue: vscrollbar.maximumValue/scale
-
- verticalValue: contentY/scale
- horizontalValue: contentX/scale
-
- onVerticalValueChanged: {
- if(!tree.blockUpdates) {
- contentY = verticalValue * scale
- vscrollbar.value = contentY
- }
- }
-
- onHorizontalValueChanged: {
- if(!tree.blockUpdates) {
- contentX = horizontalValue * scale
- hscrollbar.value = contentX
- }
- }
- }
-
- ScrollBar {
- id: hscrollbar
- orientation: Qt.Horizontal
- property int availableWidth: root.width - vscrollbar.width
- visible: contentWidth > availableWidth
- maximumValue: contentWidth > availableWidth ? tree.contentWidth - availableWidth : 0
- minimumValue: 0
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.leftMargin: frameWidth
- anchors.bottomMargin: styleitem.frameoffset
- anchors.rightMargin: vscrollbar.visible ? scrollbarExtent : (frame ? 1 : 0)
- onValueChanged: {
- if (!tree.blockUpdates)
- contentX = value
- }
- property int scrollbarExtent : styleitem.pixelMetric("scrollbarExtent");
- }
+ property string itemPosition
- ScrollBar {
- id: vscrollbar
- z:-1
- orientation: Qt.Vertical
- // We cannot bind directly to tree.height due to binding loops so we have to redo the calculation here
- property int availableHeight : root.height - (hscrollbar.visible ? hscrollbar.height : 0) - tableColumn.height
- visible: contentHeight > availableHeight
- maximumValue: contentHeight > availableHeight ? tree.contentHeight - availableHeight : 0
- minimumValue: 0
- anchors.rightMargin: styleitem.frameoffset
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.topMargin: styleitem.style == "mac" ? tableColumn.height : 0
- onValueChanged: {
- if(!tree.blockUpdates)
- time.start()
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.bottom: headerrow.bottom
+ anchors.rightMargin: -2
+ sourceComponent: root.headerDelegate
+ width: root.width - headerrow.width + 2
+ visible: root.header.length
+ z:-1
}
- anchors.bottomMargin: hscrollbar.visible ? hscrollbar.height : styleitem.frameoffset
-
- Keys.onUpPressed: if (tree.currentIndex > 0) tree.currentIndex = tree.currentIndex - 1
- Keys.onDownPressed: if (tree.currentIndex< tree.count - 1) tree.currentIndex = tree.currentIndex + 1
}
- Timer{
- id:time
- interval: 0
- onTriggered:contentY = vscrollbar.value
+ Private.ScrollAreaHelper {
+ id: scroller
+ anchors.fill: parent
+ anchors.topMargin: styleitem.style == "mac" ? tableColumn.height + frameWidth: 0
+ scrollSpeed: 2
}
StyleItem {
@@ -573,14 +584,15 @@ FocusScope{
id: styleitem
elementType: "header"
visible:false
- property int frameoffset: style === "mac" ? -1 : 0
+ contentWidth: 16
+ contentHeight: fontHeight
}
+
StyleItem {
id: rowstyleitem
- elementType: "item"
- visible:false
property color textColor: styleHint("textColor")
property color highlightedTextColor: styleHint("highlightedTextColor")
+ elementType: "item"
+ visible: false
}
- SystemPalette{id:palette}
}
diff --git a/components/TextArea.qml b/components/TextArea.qml
index f406264a..66c2ea14 100644
--- a/components/TextArea.qml
+++ b/components/TextArea.qml
@@ -14,25 +14,32 @@ ScrollArea {
property alias readOnly: edit.readOnly
property bool tabChangesFocus: false
property alias font: edit.font
+ property alias activeFocusOnPress: edit.activeFocusOnPress
highlightOnFocus: true
property int documentMargins: 4
frame: true
+ function append (string) {
+ text += "\n" + string
+ verticalScrollBar.value = verticalScrollBar.maximumValue
+ }
+
Item {
anchors.left: parent.left
anchors.top: parent.top
- height: edit.paintedHeight + area.height - viewportHeight
+ height: edit.paintedHeight + area.height - viewportHeight + 2 * documentMargins + 4
anchors.margins: documentMargins
TextEdit {
id: edit
wrapMode: TextEdit.WordWrap;
- width: 200
+ width: area.width
+ height: area.height
selectByMouse: true
readOnly: false
- focus: true
color: syspal.text
+
SystemPalette {
id: syspal
colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled
diff --git a/components/TextField.qml b/components/TextField.qml
index 4350c2c8..e6950422 100644
--- a/components/TextField.qml
+++ b/components/TextField.qml
@@ -12,16 +12,22 @@ Components.TextField {
leftMargin: 6
rightMargin: 6
- height: backgroundItem.sizeFromContents(200, 25).height
- width: 200
+ implicitWidth: backgroundItem.implicitWidth
+ implicitHeight: backgroundItem.implicitHeight
+
clip: false
+ property string styleHint
+
background: StyleItem {
anchors.fill: parent
elementType: "edit"
sunken: true
- focus: textfield.activeFocus
+ hasFocus: textfield.activeFocus
hover: containsMouse
+ hint: textfield.styleHint
+ contentWidth: 200
+ contentHeight: 25
}
Item{
@@ -36,6 +42,7 @@ Components.TextField {
anchors.bottomMargin:-4
anchors.fill: parent
visible: textfield.activeFocus
+ hint: textfield.styleHint
elementType: "focusframe"
}
}
diff --git a/components/ToolBar.qml b/components/ToolBar.qml
index fbec7973..f2ebc9d7 100644
--- a/components/ToolBar.qml
+++ b/components/ToolBar.qml
@@ -1,11 +1,11 @@
import QtQuick 2.0
+import "."
import "custom" as Components
import QtDesktop 0.1
-StyleItem{
+StyleItem {
id: toolbar
- width: 200
- height: sizeFromContents(32, 32).height
+ width: parent ? parent.width : 200
+ height: implicitHeight
elementType: "toolbar"
}
-
diff --git a/components/ToolButton.qml b/components/ToolButton.qml
index e128511a..5d597a07 100644
--- a/components/ToolButton.qml
+++ b/components/ToolButton.qml
@@ -5,30 +5,55 @@ import QtDesktop 0.1
Components.Button {
id:button
- height: 40; //styleitem.sizeFromContents(32, 32).height
- width: 40; //styleitem.sizeFromContents(32, 32).width
+ property alias containsMouse: tooltip.containsMouse
+ property string iconName
+ property string styleHint
+ property int iconSize: (backgroundItem && backgroundItem.style === "mac" && button.styleHint.indexOf("segmented") !== -1) ? 16 : 24
- StyleItem {elementType: "toolbutton"; id:styleitem }
+ implicitWidth: backgroundItem.implicitWidth
+ implicitHeight: backgroundItem.implicitHeight
- background: StyleItem {
+ TooltipArea {
+ // Note this will eat hover events
+ id: tooltip
anchors.fill: parent
+ text: button.tooltip
+ }
+
+ background: StyleItem {
id: styleitem
+ anchors.fill: parent
elementType: "toolbutton"
on: pressed | checked
sunken: pressed
raised: containsMouse
hover: containsMouse
-
+ info: __position
+ hint: button.styleHint
+ contentWidth: Math.max(textitem.paintedWidth, 32)
+ contentHeight: 32
Text {
+ id: textitem
text: button.text
anchors.centerIn: parent
visible: button.iconSource == ""
}
-
+ }
+ Image {
+ id: themeIcon
+ anchors.centerIn: parent
+ opacity: enabled ? 1 : 0.5
+ smooth: true
+ sourceSize.width: iconSize
+ property string iconPath: "image://desktoptheme/" + button.iconName
+ source: backgroundItem && backgroundItem.hasThemeIcon(iconName) ? iconPath : ""
+ fillMode: Image.PreserveAspectFit
Image {
- source: button.iconSource
+ // Use fallback icon
anchors.centerIn: parent
- opacity: enabled ? 1 : 0.5
+ sourceSize: parent.sourceSize
+ visible: (themeIcon.status != Image.Ready)
+ source: visible ? button.iconSource : ""
}
}
}
diff --git a/components/components.pro b/components/components.pro
index 37a518f3..a761830d 100644
--- a/components/components.pro
+++ b/components/components.pro
@@ -1,4 +1,4 @@
-TEMPLATE = subdirs # XXX: Avoid call the linker
+ TEMPLATE = subdirs # XXX: Avoid call the linker
TARGETPATH = QtDesktop
symbian {
@@ -9,15 +9,18 @@ symbian {
QML_FILES = \
qmldir \
+ Label.qml \
Button.qml \
ComboBox.qml \
Dial.qml \
+ Dialog.qml \
ProgressBar.qml \
ScrollBar.qml \
Switch.qml \
TableView.qml \
ToolBar.qml \
ButtonRow.qml \
+ ButtonColumn.qml \
Frame.qml \
MenuItem.qml \
Slider.qml \
@@ -31,14 +34,17 @@ QML_FILES = \
SpinBox.qml \
TabFrame.qml \
TextArea.qml \
- ChoiceList.qml \
ScrollArea.qml \
SplitterRow.qml \
+ SplitterColumn.qml \
+ StatusBar.qml \
TableColumn.qml \
- TextField.qml
+ TextField.qml \
+ ApplicationWindow.qml
QML_DIRS = \
custom \
+ private \
images
qmlfiles.files = $$QML_FILES
diff --git a/components/custom/BasicButton.qml b/components/custom/BasicButton.qml
index 2a840121..572e8130 100644
--- a/components/custom/BasicButton.qml
+++ b/components/custom/BasicButton.qml
@@ -9,12 +9,12 @@ Item {
property alias containsMouse: behavior.containsMouse
property alias checkable: behavior.checkable // button toggles between checked and !checked
property alias checked: behavior.checked
+ property bool activeFocusOnPress: false
property Component background: null
property Item backgroundItem: backgroundLoader.item
property color textColor: syspal.text;
- property bool activeFocusOnPress: false
property string tooltip
signal toolTipTriggered
@@ -22,8 +22,20 @@ Item {
// implementation
property string __position: "only"
- width: backgroundLoader.item.width
- height: backgroundLoader.item.height
+ implicitWidth: backgroundLoader.item.width
+ implicitHeight: backgroundLoader.item.height
+
+ function animateClick() {
+ behavior.pressed = true
+ behavior.clicked()
+ animateClickTimer.start()
+ }
+
+ Timer {
+ id: animateClickTimer
+ interval: 250
+ onTriggered: behavior.pressed = false
+ }
Loader {
id: backgroundLoader
diff --git a/components/custom/ButtonColumn.qml b/components/custom/ButtonColumn.qml
index 45a02696..4253db6e 100644
--- a/components/custom/ButtonColumn.qml
+++ b/components/custom/ButtonColumn.qml
@@ -28,6 +28,12 @@ Column {
property bool exclusive: true
/*
+ * Property: styleHint
+ * [string] Used to indicate special OS specific button types
+ */
+ property string styleHint
+
+ /*
* Property: checkedButton
* [string] Contains the last checked Button.
*/
diff --git a/components/custom/ButtonGroup.js b/components/custom/ButtonGroup.js
index 19d05fee..5b0d9adb 100644
--- a/components/custom/ButtonGroup.js
+++ b/components/custom/ButtonGroup.js
@@ -33,6 +33,10 @@ function build() {
nonVisibleButtons = [];
for (var i = 0, item; (item = self.children[i]); i++) {
+
+ if (item.hasOwnProperty("styleHint"))
+ item.styleHint = styleHint;
+
if (!hasChecked(item))
continue;
diff --git a/components/custom/ButtonRow.qml b/components/custom/ButtonRow.qml
index c5bc9a33..13d1380f 100644
--- a/components/custom/ButtonRow.qml
+++ b/components/custom/ButtonRow.qml
@@ -20,14 +20,19 @@ Row {
/*
* Property: exclusive
- * [bool=true] Specifies the grouping behavior. If enabled, the checked property on buttons contained
+ * [bool=false] 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 bool exclusive: false
/*
+ * Property: styleHint
+ * [string] Used to indicate special OS specific button types
+ */
+ property string styleHint
+ /*
* Property: checkedButton
* [string] Contains the last checked Button.
*/
diff --git a/components/custom/CheckBox.qml b/components/custom/CheckBox.qml
index 5a1a8696..295b41d0 100644
--- a/components/custom/CheckBox.qml
+++ b/components/custom/CheckBox.qml
@@ -1,14 +1,14 @@
import QtQuick 2.0
import "./behaviors"
-Item {
+FocusScope {
id: checkBox
signal clicked
property alias pressed: behavior.pressed
property alias checked: behavior.checked
property alias containsMouse: behavior.containsMouse
- property bool activeFocusOnPress: false
+
property Component background: null
property Item backgroundItem: backgroundLoader.item
@@ -23,10 +23,14 @@ Item {
ButtonBehavior {
id: behavior
+ focus: true
anchors.fill: parent
checkable: true
- onClicked: {if (activeFocusOnPress)checkBox.focus = true; checkBox.clicked()}
+ onClicked: {
+ if (checkBox.activeFocusOnPress)
+ checkBox.forceActiveFocus();
+ checkBox.clicked();
+ }
}
-
- SystemPalette { id: syspal }
+ Keys.onSpacePressed: {clicked(); checked = !checked; }
}
diff --git a/components/custom/ChoiceList.qml b/components/custom/ChoiceList.qml
deleted file mode 100644
index 7b4f9ceb..00000000
--- a/components/custom/ChoiceList.qml
+++ /dev/null
@@ -1,50 +0,0 @@
-import QtQuick 2.0
-import "./private" as Private // for ChoiceListPopup
-
-
-Item {
- id: choiceList
-
- property alias model: popup.model
- property alias currentIndex: popup.currentIndex
- property alias currentText: popup.currentText
- property alias popupOpen: popup.popupOpen
- property alias containsMouse: popup.containsMouse
- property alias pressed: popup.buttonPressed
-
- property Component background: null
- property Item backgroundItem: backgroundLoader.item
- property Component listItem: null
- property Component popupFrame: null
-
- property int leftMargin: 0
- property int topMargin: 0
- property int rightMargin: 0
- property int bottomMargin: 0
-
- property string popupBehavior
- width: 0
- height: 0
-
- property bool activeFocusOnPress: true
-
- Loader {
- id: backgroundLoader
- property alias styledItem: choiceList
- sourceComponent: background
- anchors.fill: parent
- property string currentItemText: model.get(currentIndex).text
- }
-
- Private.ChoiceListPopup {
- // NB: This ChoiceListPopup is also the mouse area
- // for the component (to enable drag'n'release)
- id: popup
- listItem: choiceList.listItem
- popupFrame: choiceList.popupFrame
- }
-
- Keys.onSpacePressed: { choiceList.popupOpen = !choiceList.popupOpen }
- Keys.onUpPressed: { if (currentIndex < model.count - 1) currentIndex++ }
- Keys.onDownPressed: {if (currentIndex > 0) currentIndex-- }
-}
diff --git a/components/custom/GroupBox.qml b/components/custom/GroupBox.qml
index 1803f90a..1c25fa8d 100644
--- a/components/custom/GroupBox.qml
+++ b/components/custom/GroupBox.qml
@@ -1,10 +1,10 @@
import QtQuick 2.0
-FocusScope {
+Item {
id: groupbox
- width: Math.max(200, contentWidth + loader.leftMargin + loader.rightMargin)
- height: contentHeight + loader.topMargin + loader.bottomMargin
+ implicitWidth: adjustToContentSize ? Math.max(200, contentWidth + loader.leftMargin + loader.rightMargin) : 100
+ implicitHeight: adjustToContentSize ? contentHeight + loader.topMargin + loader.bottomMargin : 100
default property alias data: content.data
@@ -17,38 +17,38 @@ FocusScope {
property Component background: null
property Item backgroundItem: loader.item
- property CheckBox checkbox: check
+ property Item checkbox: check
property alias checked: check.checked
-
+ property bool adjustToContentSize: false // Resizes groupbox to fit contents.
+ // Note when using this, you cannot anchor children
Loader {
id: loader
anchors.fill: parent
- property int topMargin: 22
+ property int topMargin: title.length > 0 || checkable ? 22 : 4
property int bottomMargin: 4
property int leftMargin: 4
property int rightMargin: 4
-
property alias styledItem: groupbox
sourceComponent: background
-
- Item {
- id:content
- z: 1
- opacity: contentOpacity
- anchors.topMargin: loader.topMargin
- anchors.leftMargin: 8
- anchors.top:parent.top
- anchors.left:parent.left
- enabled: (!checkable || checkbox.checked)
- }
-
- CheckBox {
- id: check
- checked: true
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- height: loader.topMargin
- }
+ }
+ CheckBox {
+ id: check
+ checked: true
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: loader.topMargin
+ }
+ Item {
+ id:content
+ z: 1
+ focus: true
+ opacity: contentOpacity
+ anchors.topMargin: loader.topMargin
+ anchors.leftMargin: 8
+ anchors.rightMargin: 8
+ anchors.bottomMargin: 8
+ anchors.fill: parent
+ enabled: (!checkable || checkbox.checked)
}
}
diff --git a/components/custom/ProgressBar.qml b/components/custom/ProgressBar.qml
index 3e85e139..6b42470e 100644
--- a/components/custom/ProgressBar.qml
+++ b/components/custom/ProgressBar.qml
@@ -17,9 +17,6 @@ Item {
property int minimumWidth: 0
property int minimumHeight: 0
- width: minimumWidth
- height: minimumHeight
-
property Component background: null
property Item backgroundItem: groove.item
diff --git a/components/custom/SpinBox.qml b/components/custom/SpinBox.qml
index 654c8dc7..657f0f3a 100644
--- a/components/custom/SpinBox.qml
+++ b/components/custom/SpinBox.qml
@@ -16,12 +16,6 @@ FocusScope {
property int rightMargin: 0
property int bottomMargin: 0
- 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
diff --git a/components/custom/Splitter.qml b/components/custom/Splitter.qml
new file mode 100644
index 00000000..417a6b31
--- /dev/null
+++ b/components/custom/Splitter.qml
@@ -0,0 +1,405 @@
+import QtQuick 1.1
+import QtDesktop 0.1
+
+Splitter {
+ id: root
+ default property alias items: splitterItems.children
+ property alias handles: splitterHandles.children
+ property Component handleBackground: Rectangle { width:3; color: "black" }
+ property int handleWidth: -1
+ property real preferredSize: 0
+ property int orientation: Qt.Horizontal
+
+ clip: true
+ Component.onCompleted: d.init();
+ onWidthChanged: d.updateLayout();
+ onHeightChanged: d.updateLayout();
+
+ QtObject {
+ id: d
+
+ property bool horizontal: orientation == Qt.Horizontal
+ property string size: horizontal ? "width" : "height"
+ property string minimum: horizontal ? "minimumWidth" : "minimumHeight"
+ property string maximum: horizontal ? "maximumWidth" : "maximumHeight"
+
+ property string offset: horizontal ? "x" : "y"
+ property int expandingIndex: -1
+ property bool updateLayoutGuard: true
+ property bool itemWidthGuard: false
+ property bool itemExpandingGuard: true
+
+ function init()
+ {
+ for (var i=0; i<items.length; ++i) {
+ var item = items[i];
+
+ item.Splitter.itemIndex = i
+ // Assign one, and only one, item to be expanding:
+ if (item.Splitter.expanding === true) {
+ if (d.expandingIndex === -1 && item.visible === true)
+ d.expandingIndex = i
+ else
+ item.Splitter.expanding = false
+ }
+
+ // Anchor each item to fill out all space vertically:
+ if (d.horizontal) {
+ item.anchors.top = splitterItems.top
+ item.anchors.bottom = splitterItems.bottom
+ } else {
+ item.anchors.left = splitterItems.left
+ item.anchors.right = splitterItems.right
+
+ }
+
+ // Listen for changes to width and expanding:
+ propertyChangeListener.createObject(item, {"itemIndex":i});
+ if (i < items.length-1) {
+ // Create a handle for the item, unless its the last:
+ var handle = handleBackgroundLoader.createObject(splitterHandles, {"handleIndex":i});
+
+ if (d.horizontal) {
+ handle.anchors.top = splitterHandles.top
+ handle.anchors.bottom = splitterHandles.bottom
+ } else {
+ handle.anchors.left = splitterHandles.left
+ handle.anchors.right = splitterHandles.right
+ }
+ }
+ }
+
+ if (d.expandingIndex === -1) {
+ // INVARIANT: No item was set as expanding.
+ // We then choose the last visible item instead:
+ d.expandingIndex = items.length - 1
+ for (i=items.length-1; i>=0; --i) {
+ var item = items[i]
+ if (item.visible === true) {
+ d.expandingIndex = i
+ item = items[i]
+ break
+ }
+ }
+ item.Splitter.expanding = true
+ }
+
+ d.itemExpandingGuard = false
+ d.updateLayoutGuard = false
+ d.updateLayout()
+ }
+
+ function accumulatedSize(firstIndex, lastIndex, includeExpandingMinimum)
+ {
+ // Go through items and handles, and
+ // calculate their acummulated width.
+ var w = 0
+ for (var i=firstIndex; i<lastIndex; ++i) {
+ var item = items[i]
+ if (item.visible) {
+ if (i !== d.expandingIndex)
+ w += item[d.size];
+ else if (includeExpandingMinimum && item.Splitter[minimum] != -1)
+ w += item[minimum]
+ }
+
+ var handle = handles[i]
+ if (handle && items[i + ((d.expandingIndex > i) ? 0 : 1)].visible)
+ w += handle[d.size]
+ }
+ return w
+ }
+
+ function updateLayout()
+ {
+ // This function will reposition both handles and
+ // items according to the _width of the each item_
+ if (items.length === 0)
+ return;
+ if (d.updateLayoutGuard === true)
+ return
+ d.updateLayoutGuard = true
+
+ // Use a temporary variable to store values to avoid breaking
+ // property bindings when the value does not actually change:
+ var newValue
+
+ // Ensure all items within min/max:
+ for (var i=0; i<items.length; ++i) {
+ if (i !== d.expandingIndex) {
+ item = items[i];
+ // If the item is using percentage width, convert
+ // that number to real width now:
+ if (item.Splitter.percentageSize !== -1) {
+ newValue = item.Splitter.percentageSize * (root[d.size] / 100)
+ if (newValue !== item[d.size])
+ item[d.size] = newValue
+ }
+ // Ensure item width is not more than maximumSize:
+ if (item.Splitter[maximum] !== -1) {
+ newValue = Math.min(item[d.size], item.Splitter[maximum])
+ if (newValue !== item[d.size])
+ item[d.size] = newValue
+ }
+ // Ensure item width is not more less minimumWidth:
+ if (item.Splitter[minimum] !== -1) {
+ newValue = Math.max(item[d.size], item.Splitter[minimum])
+ if (newValue !== item[d.size])
+ item[d.size] = newValue
+ }
+ }
+ }
+
+ // Special case: set width of expanding item to available space:
+ newValue = root[d.size] - d.accumulatedSize(0, items.length, false);
+ var expandingItem = items[d.expandingIndex]
+ var expandingMinimum = 0
+ if (expandingItem.Splitter[minimum] !== -1)
+ expandingMinimum = expandingItem.Splitter[minimum]
+ newValue = Math.max(newValue, expandingMinimum)
+ if (expandingItem[d.size] !== 0 && expandingItem.Splitter.percentageSize !== -1)
+ expandingItem.Splitter.percentageSize = newValue * (100 / root[d.size])
+ if (expandingItem[d.size] !== newValue)
+ expandingItem[d.size] = newValue
+
+ // Then, position items and handles according to their width:
+ var item, lastVisibleItem
+ var handle, lastVisibleHandle
+ var newpreferredSize = expandingMinimum - expandingItem[d.size]
+
+ for (i=0; i<items.length; ++i) {
+ // Position item to the right of the previous visible handle:
+ item = items[i];
+ if (item.visible) {
+ if (lastVisibleHandle) {
+ newValue = lastVisibleHandle[d.offset] + lastVisibleHandle[d.size]
+ if (newValue !== item[d.offset])
+ item[d.offset] = newValue
+ } else {
+ newValue = 0
+ if (newValue !== item[d.offset])
+ item[d.offset] = newValue
+ }
+ newpreferredSize += item[d.size]
+ lastVisibleItem = item
+ }
+
+ // Position handle to the right of the previous visible item. We use an alterative way of
+ // checking handle visibility because that property might not have updated correctly yet:
+ handle = handles[i]
+ if (handle && items[i + ((d.expandingIndex > i) ? 0 : 1)].visible) {
+ newValue = lastVisibleItem[d.offset] + Math.max(0, lastVisibleItem[d.size])
+ if (newValue !== handle[d.offset])
+ handle[d.offset] = newValue
+ newpreferredSize += handle[d.size]
+ lastVisibleHandle = handle
+ }
+ }
+
+ root.preferredSize = newpreferredSize
+ d.updateLayoutGuard = false
+ }
+ }
+
+ Component {
+ id: handleBackgroundLoader
+ Loader {
+ id: myHandle
+ property int handleIndex: 0
+ property Item handle: myHandle
+ property Item splitterItem: items[handleIndex + ((d.expandingIndex > handleIndex) ? 0 : 1)]
+
+ // 'splitterRow' should be an alias, but that fails to resolve runtime:
+ property Item splitterRow: root
+ property Item background: item
+
+ visible: splitterItem.visible
+ sourceComponent: handleBackground
+ onWidthChanged: d.updateLayout()
+
+ onXChanged: {
+ // Moving the handle means resizing an item. Which one,
+ // left or right, depends on where the expanding item is.
+ // 'updateLayout' will override in case new width violates max/min.
+ // And 'updateLayout will be triggered when an item changes width.
+ if (d.updateLayoutGuard)
+ return
+
+ var leftHandle, leftItem, rightItem, rightHandle
+ var leftEdge, rightEdge, newWidth, leftStopX, rightStopX
+ var i
+
+ if (d.expandingIndex > handleIndex) {
+ // Resize item to the left.
+ // Ensure that the handle is not crossing other handles. So
+ // find the first visible handle to the left to determine the left edge:
+ leftEdge = 0
+ for (i=handleIndex-1; i>=0; --i) {
+ leftHandle = handles[i]
+ if (leftHandle.visible) {
+ leftEdge = leftHandle[d.offset] + leftHandle[d.size]
+ break;
+ }
+ }
+
+ // Ensure: leftStopX >= myHandle[d.offset] >= rightStopX
+ var min = d.accumulatedSize(handleIndex+1, items.length, true)
+ rightStopX = root[d.size] - min - myHandle[d.size]
+ leftStopX = Math.max(leftEdge, myHandle[d.offset])
+ myHandle[d.offset] = Math.min(rightStopX, Math.max(leftStopX, myHandle[d.offset]))
+
+ newWidth = myHandle[d.offset] - leftEdge
+ leftItem = items[handleIndex]
+ if (root[d.size] != 0 && leftItem.Splitter.percentageSize !== -1)
+ leftItem.Splitter.percentageSize = newWidth * (100 / root[d.size])
+ // The next line will trigger 'updateLayout' inside 'propertyChangeListener':
+ leftItem[d.size] = newWidth
+ } else {
+ // Resize item to the right.
+ // Ensure that the handle is not crossing other handles. So
+ // find the first visible handle to the right to determine the right edge:
+ rightEdge = root[d.size]
+ for (i=handleIndex+1; i<handles.length; ++i) {
+ rightHandle = handles[i]
+ if (rightHandle.visible) {
+ rightEdge = rightHandle[d.offset]
+ break;
+ }
+ }
+
+ // Ensure: leftStopX <= myHandle[d.offset] <= rightStopX
+ var min = d.accumulatedSize(0, handleIndex+1, true)
+ leftStopX = min - myHandle[d.size]
+ rightStopX = Math.min((rightEdge - myHandle[d.size]), myHandle[d.offset])
+ myHandle[d.offset] = Math.max(leftStopX, Math.min(myHandle[d.offset], rightStopX))
+
+ newWidth = rightEdge - (myHandle[d.offset] + myHandle[d.size])
+ rightItem = items[handleIndex+1]
+ if (root[d.size] !== 0 && rightItem[d.percentageSize] !== -1)
+ rightItem.Splitter.percentageSize = newWidth * (100 / root[d.size])
+ // The next line will trigger 'updateLayout' inside 'propertyChangeListener':
+ rightItem[d.size] = newWidth
+ }
+ }
+ }
+ }
+
+ Item {
+ id: splitterItems
+ anchors.fill: parent
+ }
+ Item {
+ id: splitterHandles
+ anchors.fill: parent
+ }
+
+ Component {
+ // This dummy item becomes a child of all
+ // items it the splitter, just to provide a way
+ // to listen for changes to their width, expanding etc.
+ id: propertyChangeListener
+ Item {
+ id: target
+ width: parent[d.size]
+ property bool expanding: parent.Splitter.expanding
+ property real percentageSize: parent.Splitter.percentageSize
+ property real minimumWidth: parent.Splitter[d.minimum]
+ property real maximumSize: parent.Splitter[d.maximum]
+ property int itemIndex: parent.Splitter.itemIndex
+
+ onPercentageSizeChanged: d.updateLayout();
+ onMinimumWidthChanged: d.updateLayout();
+ onMaximumSizeChanged: d.updateLayout();
+ onExpandingChanged: updateExpandingIndex()
+
+ function updateExpandingIndex()
+ {
+ // The following code is needed to avoid a binding
+ // loop, since we might change 'expanding' again to a different item:
+ if (d.itemExpandingGuard === true)
+ return
+ d.itemExpandingGuard = true
+ // break binding:
+ expanding = false
+
+ // 'expanding' follows radio button behavior:
+ // First, find the new expanding item:
+ var newIndex = items.length-1
+ for (var i=0; i<items.length; ++i) {
+ var item = items[i]
+ if (i !== d.expandingIndex && item.Splitter.expanding === true && item.visible === true) {
+ newIndex = i
+ break
+ }
+ }
+ item = items[newIndex]
+ if (item.visible === false) {
+ // So now we ended up with the last item in the splitter to be
+ // expanding, but it turns out to not be visible. So we need to
+ // traverse backwards again to find one that is visible...
+ for (i=items.length-2; i>=0; --i) {
+ var item = items[i]
+ if (item.visible === true) {
+ newIndex = i
+ item = items[newIndex]
+ break
+ }
+ }
+ }
+
+ // Tell the found item that it is expanding:
+ if (item.Splitter.expanding !== true)
+ item.Splitter.expanding = true
+ // ...and the old one that it is not:
+ if (newIndex !== d.expandingIndex) {
+ item = items[d.expandingIndex]
+ if (item.Splitter.expanding !== false)
+ item.Splitter.expanding = false
+ }
+ // update index:
+ d.expandingIndex = newIndex
+ d.updateLayout();
+ // recreate binding:
+ expanding = function() { return parent.Splitter.expanding }
+ d.itemExpandingGuard = false
+ }
+
+ function handleSizeChanged() {
+ // We need to update the layout.
+ // The following code is needed to avoid a binding
+ // loop, since we might change 'width' again to a different value:
+ if (d.itemWidthGuard === true)
+ return
+ d.itemWidthGuard = true
+ // Break binding:
+ this[d.size] = 0
+
+ d.updateLayout()
+
+ // Restablish binding:
+ width = function() { return parent[d.size]; }
+ d.itemWidthGuard = false
+ }
+
+ onWidthChanged: handleSizeChanged()
+ onHeightChanged: handleSizeChanged()
+ onVisibleChanged: {
+ // Hiding the expanding item forces us to
+ // select a new one (and therefore not recommended):
+ if (d.expandingIndex === itemIndex) {
+ updateExpandingIndex()
+ } else {
+ if (visible) {
+ // Try to keep all items within the SplitterRow. When an item
+ // has been hidden, the expanding item might no longer be large enough
+ // to give away space to the new items width. So we need to resize:
+ var overflow = d.accumulatedSize(0, items.length, true) - root[d.size];
+ if (overflow > 0)
+ parent[d.size] -= overflow
+ }
+ d.updateLayout()
+ }
+ }
+ }
+ }
+}
diff --git a/components/custom/SplitterRow.qml b/components/custom/SplitterRow.qml
deleted file mode 100644
index af8de528..00000000
--- a/components/custom/SplitterRow.qml
+++ /dev/null
@@ -1,494 +0,0 @@
-import QtQuick 1.1
-import "private"
-
-/*
-*
-* SplitterRow
-*
-* SplitterRow is a component that provides a way to layout items horisontally with
-* a draggable splitter added in-between each item.
-*
-* Add items to the SplitterRow by inserting them as child items. The splitter handle
-* is outsourced as a delegate (handleBackground). To enable the user to drag the handle,
-* it will need to contain a mouse area that communicates with the SplitterRow by binding
-* 'drag.target: handle'. The 'handle' property points to the handle item that embedds
-* the delegate. To change handle positions, either change 'x' (or 'width') of 'handle', or
-* change the width of the child items inside the SplitterRow. If you set the visibility
-* of a child item to false, the corresponding handle will also be hidden, and the
-* SplitterRow will perform a layout update to fill up available space.
-*
-* There will always be one (and only one) item in the SplitterRow that is 'expanding'.
-* The expanding item is the child that will get all the remaining space in the SplitterRow
-* (down to its own mimimumSize) when all other items have been layed out.
-* This means that that 'width', 'percentageWidth' and 'maximumWidth' will be ignored for this item.
-* By default, the last visible child item of the SplitterRow will be 'expanding'.
-*
-* A handle can belong to the item on the left side, or the right side, of the handle. Which one depends
-* on the expaning item. If the expanding item is to the right of the handle, the
-* handle will belong to the item on the left. If it is to the left, it will belong to the item on the
-* right. This will again control which item that gets resized when the user drags a handle, and which
-* handle that gets hidden when an item is told to hide.
-*
-* NB: Since SplitterRow might modify geometry properties like 'width' and 'x' of child items
-* to e.g. ensure they stay within minimumWidth/maximumWidth, explicit expression bindings
-* to such properties can easily be broken up by the SplitterRow, and is not recommended.
-*
-* The SplitterRow contains the following API:
-*
-* Component handleBackground - delegate that will be instanciated between each
-* child item. Inside the delegate, the following properties are available:
-* int handleIndex - specifies the index of the splitter handle. The handle
-* between the first and the second item will get index 0, the next handle index 1 etc.
-* Item handle - convenience property that points to the item where the handle background is
-* instanciated as a child. Identical to splitterRow.handles[handleIndex]. The handle
-* background iteself can be accessed through handle.item.
-* Modify 'handle.x' to move the handle (or change 'width' of SplitterRow child items).
-* Item splitterItem - convenience property that points to the child item that the handle controls.
-* Also refer to information about the expanding item above.
-* Item splitterRow - points to the SplitterRow that the handle is in.
-* List<Item> items - contains the list of child items in the SplitterRow. Currently read-only.
-* List<Item> handles - contains the list of splitter handles in the SplitterRow. Note that this list will
-* be populated after all child items has completed, so accessing it from Component.onCompleted
-* inside a SplitterRow child item will not work. To get to the handle background, access the
-* 'background' property of the handle, e.g. handles[0].background. Read-only.
-* real preferredWidth - contains the accumulated with of all child items and handles, except
-* the expanding item. If the expanding item has a minimum width, the minimum width will
-* be included.
-*
-* The following properties can optionally be added for each child item of SplitterRow:
-*
-* real minimumWidth - ensures that the item cannot be resized below the
-* given value. A value of -1 will disable it.
-* real maximumWidth - ensures that the item cannot be resized above the
-* given value. A value of -1 will disable it.
-* real percentageWidth - This value specifies a percentage (0 - 100) of the width of the
-* SplitterRow width. If the width of the SplitterRow change, the width of the item will
-* change as well. 'percentageWidth' have precedence over 'width', which means that
-* SplitterRow will ignore any assignments to 'width'. A value of -1 disables it.
-* bool expanding - See explanation of 'expanding' above. If set to true, the current item
-* will be the expanding item in the SplitterRow. If set to false, the SplitterRow will
-* autmatically choose the last visible child of the SplitterRow as expanding instead.
-* int itemIndex - will be assigned a read-only value with the item index. Can be used to e.g. look-up
-* the handles sourrounding the item (parent.handles[itemIndex])
-*
-* Example:
-*
-* To create a SplitterRow with three items, and let
-* the center item be the one that should be expanding, one
-* could do the following:
-*
-* SplitterRow {
-* anchors.fill: parent
-*
-* handleBackground: Rectangle {
-* width: 1
-* color: "black"
-*
-* MouseArea {
-* anchors.fill: parent
-* anchors.leftMargin: -2
-* anchors.rightMargin: -2
-* drag.axis: Qt.YAxis
-* drag.target: handle
-* }
-* }
-*
-* Rectangle {
-* property real maximumWidth: 400
-* color: "gray"
-* width: 200
-* }
-* Rectangle {
-* property real minimumWidth: 50
-* property bool expanding: true
-* color: "darkgray"
-* }
-* Rectangle {
-* color: "gray"
-* width: 200
-* }
-* }
-*/
-
-Item {
- id: root
- default property alias items: splitterItems.children
- property alias handles: splitterHandles.children
- property Component handleBackground: Rectangle { width:3; color: "black" }
- property real preferredWidth: 0
- clip: true
-
- Component.onCompleted: d.init();
- onWidthChanged: d.updateLayout();
-
- QtObject {
- id: d
- property int expandingIndex: -1
- property bool updateLayoutGuard: true
- property bool itemWidthGuard: false
- property bool itemExpandingGuard: true
-
- function init()
- {
- for (var i=0; i<items.length; ++i) {
- var item = items[i];
- // If the item has an 'itemIndex' defined, assign it a value:
- if (item.itemIndex != undefined)
- item.itemIndex = i
-
- // Assign one, and only one, item to be expanding:
- if (item.expanding != undefined && item.expanding === true) {
- if (d.expandingIndex === -1 && item.visible === true)
- d.expandingIndex = i
- else
- item.expanding = false
- }
-
- // Anchor each item to fill out all space vertically:
- item.anchors.top = splitterItems.top
- item.anchors.bottom = splitterItems.bottom
-
- // Listen for changes to width and expanding:
- propertyChangeListener.createObject(item, {"itemIndex":i});
- if (i < items.length-1) {
- // Create a handle for the item, unless its the last:
- var handle = handleBackgroundLoader.createObject(splitterHandles, {"handleIndex":i});
-
- handle.anchors.top = splitterHandles.top
- handle.anchors.bottom = splitterHandles.bottom
- }
- }
-
- if (d.expandingIndex === -1) {
- // INVARIANT: No item was set as expanding.
- // We then choose the last visible item instead:
- d.expandingIndex = items.length - 1
- for (i=items.length-1; i>=0; --i) {
- var item = items[i]
- if (item.visible === true) {
- d.expandingIndex = i
- item = items[i]
- break
- }
- }
- if (item.expanding != undefined)
- item.expanding = true
- }
-
- d.itemExpandingGuard = false
- d.updateLayoutGuard = false
- d.updateLayout()
- }
-
- function accumulatedWidth(firstIndex, lastIndex, includeExpandingMinimum)
- {
- // Go through items and handles, and
- // calculate their acummulated width.
- var w = 0
- for (var i=firstIndex; i<lastIndex; ++i) {
- var item = items[i]
- if (item.visible) {
- if (i !== d.expandingIndex)
- w += item.width;
- else if (includeExpandingMinimum && item.minimumWidth != undefined && item.minimumWidth != -1)
- w += item.minimumWidth
- }
-
- var handle = handles[i]
- if (handle && items[i + ((d.expandingIndex > i) ? 0 : 1)].visible)
- w += handle.width
- }
- return w
- }
-
- function updateLayout()
- {
- // This function will reposition both handles and
- // items according to the _width of the each item_
- if (items.length === 0)
- return;
- if (d.updateLayoutGuard === true)
- return
- d.updateLayoutGuard = true
-
- // Use a temporary variable to store values to avoid breaking
- // property bindings when the value does not actually change:
- var newValue
-
- // Ensure all items within min/max:
- for (var i=0; i<items.length; ++i) {
- if (i !== d.expandingIndex) {
- item = items[i];
- // If the item is using percentage width, convert
- // that number to real width now:
- if (item.percentageWidth != undefined && item.percentageWidth !== -1) {
- newValue = item.percentageWidth * (root.width / 100)
- if (newValue !== item.width)
- item.width = newValue
- }
- // Ensure item width is not more than maximumWidth:
- if (item.maximumWidth != undefined && item.maximumWidth != -1) {
- newValue = Math.min(item.width, item.maximumWidth)
- if (newValue !== item.width)
- item.width = newValue
- }
- // Ensure item width is not more less minimumWidth:
- if (item.minimumWidth != undefined && item.minimumWidth != -1) {
- newValue = Math.max(item.width, item.minimumWidth)
- if (newValue !== item.width)
- item.width = newValue
- }
- }
- }
-
- // Special case: set width of expanding item to available space:
- newValue = root.width - d.accumulatedWidth(0, items.length, false);
- var expandingItem = items[d.expandingIndex]
- var expandingMinimum = 0
- if (expandingItem.minimumWidth != undefined && expandingItem.minimumWidth != -1)
- expandingMinimum = expandingItem.minimumWidth
- newValue = Math.max(newValue, expandingMinimum)
- if (expandingItem.width != 0 && expandingItem.percentageWidth != undefined && expandingItem.percentageWidth !== -1)
- expandingItem.percentageWidth = newValue * (100 / root.width)
- if (expandingItem.width !== newValue)
- expandingItem.width = newValue
-
- // Then, position items and handles according to their width:
- var item, lastVisibleItem
- var handle, lastVisibleHandle
- var newPreferredWidth = expandingMinimum - expandingItem.width
-
- for (i=0; i<items.length; ++i) {
- // Position item to the right of the previous visible handle:
- item = items[i];
- if (item.visible) {
- if (lastVisibleHandle) {
- newValue = lastVisibleHandle.x + lastVisibleHandle.width
- if (newValue !== item.x)
- item.x = newValue
- } else {
- newValue = 0
- if (newValue !== item.x)
- item.x = newValue
- }
- newPreferredWidth += item.width
- lastVisibleItem = item
- }
-
- // Position handle to the right of the previous visible item. We use an alterative way of
- // checking handle visibility because that property might not have updated correctly yet:
- handle = handles[i]
- if (handle && items[i + ((d.expandingIndex > i) ? 0 : 1)].visible) {
- newValue = lastVisibleItem.x + Math.max(0, lastVisibleItem.width)
- if (newValue !== handle.x)
- handle.x = newValue
- newPreferredWidth += handle.width
- lastVisibleHandle = handle
- }
- }
-
- root.preferredWidth = newPreferredWidth
- d.updateLayoutGuard = false
- }
- }
-
- Component {
- id: handleBackgroundLoader
- Loader {
- id: myHandle
- property int handleIndex: 0
- property Item handle: myHandle
- property Item splitterItem: items[handleIndex + ((d.expandingIndex > handleIndex) ? 0 : 1)]
-
- // 'splitterRow' should be an alias, but that fails to resolve runtime:
- property Item splitterRow: root
- property Item background: item
-
- visible: splitterItem.visible
- sourceComponent: handleBackground
- onWidthChanged: d.updateLayout()
-
- onXChanged: {
- // Moving the handle means resizing an item. Which one,
- // left or right, depends on where the expanding item is.
- // 'updateLayout' will override in case new width violates max/min.
- // And 'updateLayout will be triggered when an item changes width.
- if (d.updateLayoutGuard)
- return
-
- var leftHandle, leftItem, rightItem, rightHandle
- var leftEdge, rightEdge, newWidth, leftStopX, rightStopX
- var i
-
- if (d.expandingIndex > handleIndex) {
- // Resize item to the left.
- // Ensure that the handle is not crossing other handles. So
- // find the first visible handle to the left to determine the left edge:
- leftEdge = 0
- for (i=handleIndex-1; i>=0; --i) {
- leftHandle = handles[i]
- if (leftHandle.visible) {
- leftEdge = leftHandle.x + leftHandle.width
- break;
- }
- }
-
- // Ensure: leftStopX >= myHandle.x >= rightStopX
- var min = d.accumulatedWidth(handleIndex+1, items.length, true)
- rightStopX = root.width - min - myHandle.width
- leftStopX = Math.max(leftEdge, myHandle.x)
- myHandle.x = Math.min(rightStopX, Math.max(leftStopX, myHandle.x))
-
- newWidth = myHandle.x - leftEdge
- leftItem = items[handleIndex]
- if (root.width != 0 && leftItem.percentageWidth != undefined && leftItem.percentageWidth !== -1)
- leftItem.percentageWidth = newWidth * (100 / root.width)
- // The next line will trigger 'updateLayout' inside 'propertyChangeListener':
- leftItem.width = newWidth
- } else {
- // Resize item to the right.
- // Ensure that the handle is not crossing other handles. So
- // find the first visible handle to the right to determine the right edge:
- rightEdge = root.width
- for (i=handleIndex+1; i<handles.length; ++i) {
- rightHandle = handles[i]
- if (rightHandle.visible) {
- rightEdge = rightHandle.x
- break;
- }
- }
-
- // Ensure: leftStopX <= myHandle.x <= rightStopX
- var min = d.accumulatedWidth(0, handleIndex+1, true)
- leftStopX = min - myHandle.width
- rightStopX = Math.min((rightEdge - myHandle.width), myHandle.x)
- myHandle.x = Math.max(leftStopX, Math.min(myHandle.x, rightStopX))
-
- newWidth = rightEdge - (myHandle.x + myHandle.width)
- rightItem = items[handleIndex+1]
- if (root.width != 0 && rightItem.percentageWidth != undefined && rightItem.percentageWidth !== -1)
- rightItem.percentageWidth = newWidth * (100 / root.width)
- // The next line will trigger 'updateLayout' inside 'propertyChangeListener':
- rightItem.width = newWidth
- }
- }
- }
- }
-
- Item {
- id: splitterItems
- anchors.fill: parent
- }
- Item {
- id: splitterHandles
- anchors.fill: parent
- }
-
- Component {
- // This dummy item becomes a child of all
- // items it the splitter, just to provide a way
- // to listen for changes to their width, expanding etc.
- id: propertyChangeListener
- Item {
- id: target
- width: parent.width
- property bool expanding: (parent.expanding != undefined) ? parent.expanding : false
- property real percentageWidth: (parent.percentageWidth != undefined) ? parent.percentageWidth : -1
- property real minimumWidth: (parent.minimumWidth != undefined) ? parent.minimumWidth : -1
- property real maximumWidth: (parent.maximumWidth != undefined) ? parent.maximumWidth : -1
- property int itemIndex: 0
-
- onPercentageWidthChanged: d.updateLayout();
- onMinimumWidthChanged: d.updateLayout();
- onMaximumWidthChanged: d.updateLayout();
- onExpandingChanged: updateExpandingIndex()
-
- function updateExpandingIndex()
- {
- // The following code is needed to avoid a binding
- // loop, since we might change 'expanding' again to a different item:
- if (d.itemExpandingGuard === true)
- return
- d.itemExpandingGuard = true
- // break binding:
- expanding = false
-
- // 'expanding' follows radio button behavior:
- // First, find the new expanding item:
- var newIndex = items.length-1
- for (var i=0; i<items.length; ++i) {
- var item = items[i]
- if (i !== d.expandingIndex && item.expanding != undefined && item.expanding === true && item.visible === true) {
- newIndex = i
- break
- }
- }
- item = items[newIndex]
- if (item.visible === false) {
- // So now we ended up with the last item in the splitter to be
- // expanding, but it turns out to not be visible. So we need to
- // traverse backwards again to find one that is visible...
- for (i=items.length-2; i>=0; --i) {
- var item = items[i]
- if (item.visible === true) {
- newIndex = i
- item = items[newIndex]
- break
- }
- }
- }
-
- // Tell the found item that it is expanding:
- if (item.expanding != undefined && item.expanding !== true)
- item.expanding = true
- // ...and the old one that it is not:
- if (newIndex !== d.expandingIndex) {
- item = items[d.expandingIndex]
- if (item.expanding != undefined && item.expanding !== false)
- item.expanding = false
- }
- // update index:
- d.expandingIndex = newIndex
- d.updateLayout();
- // recreate binding:
- expanding = function() { return (parent.expanding != undefined) ? parent.expanding : false; }
- d.itemExpandingGuard = false
- }
-
- onWidthChanged: {
- // We need to update the layout.
- // The following code is needed to avoid a binding
- // loop, since we might change 'width' again to a different value:
- if (d.itemWidthGuard === true)
- return
- d.itemWidthGuard = true
- // Break binding:
- width = 0
-
- d.updateLayout()
-
- // Restablish binding:
- width = function() { return parent.width; }
- d.itemWidthGuard = false
- }
-
- onVisibleChanged: {
- // Hiding the expanding item forces us to
- // select a new one (and therefore not recommended):
- if (d.expandingIndex === itemIndex) {
- updateExpandingIndex()
- } else {
- if (visible) {
- // Try to keep all items within the SplitterRow. When an item
- // has been hidden, the expanding item might no longer be large enough
- // to give away space to the new items width. So we need to resize:
- var overflow = d.accumulatedWidth(0, items.length, true) - root.width;
- if (overflow > 0)
- parent.width -= overflow
- }
- d.updateLayout()
- }
- }
- }
- }
-}
diff --git a/components/custom/TextField.qml b/components/custom/TextField.qml
index 8d9d3ac1..39792de0 100644
--- a/components/custom/TextField.qml
+++ b/components/custom/TextField.qml
@@ -24,6 +24,7 @@ FocusScope {
property alias echoMode: textInput.echoMode
property alias cursorPosition: textInput.cursorPosition
property alias inputMethodHints: textInput.inputMethodHints
+ property alias activeFocusOnPress: textInput.activeFocusOnPress
property color textColor: syspal.text
property color backgroundColor: syspal.base
@@ -75,12 +76,6 @@ FocusScope {
return textInput.positionToRectangle(p);
}
- width: Math.max(minimumWidth,
- textInput.width + leftMargin + rightMargin)
-
- height: Math.max(minimumHeight,
- textInput.height + topMargin + bottomMargin)
-
// Implementation
clip: true
@@ -106,7 +101,6 @@ FocusScope {
TextInput { // see QTBUG-14936
id: textInput
selectByMouse:true
- focus: true
anchors.leftMargin: leftMargin
anchors.topMargin: topMargin
@@ -118,7 +112,7 @@ FocusScope {
anchors.verticalCenter: parent.verticalCenter
color: syspal.text
- echoMode: passwordMode ? _hints.passwordEchoMode : TextInput.Normal
+ echoMode: passwordMode ? TextInput.Password : TextInput.Normal
}
diff --git a/components/custom/components.pro b/components/custom/components.pro
index 62e0651d..e063d91d 100644
--- a/components/custom/components.pro
+++ b/components/custom/components.pro
@@ -17,8 +17,7 @@ QML_FILES = \
ButtonGroup.js \
Button.qml \
CheckBox.qml \
- ChoiceList.qml \
- SplitterRow.qml \
+ Splitter.qml \
ProgressBar.qml \
RadioButton.qml \
ScrollDecorator.qml \
diff --git a/components/custom/private/ChoiceListPopup.qml b/components/custom/private/ChoiceListPopup.qml
deleted file mode 100644
index 7d6e29a0..00000000
--- a/components/custom/private/ChoiceListPopup.qml
+++ /dev/null
@@ -1,322 +0,0 @@
-import QtQuick 2.0
-
-MouseArea {
- id: popup
-
- // There is no global z-ordering that can stack this popup in front, so we
- // need to reparent it to the root item to fake it upon showing the popup.
- // In that case, the popup will also fill the whole window to allow the user to
- // close the popup by clicking anywhere in the window. Letting the popup act as the mouse
- // area for the button that 'owns' it is also nessesary to support drag'n'release behavior.
-
- // The 'popupframe' delegate will be told to show or hide by assigning
- // opacity to 1 or 0, respectively.
-
- anchors.fill: parent
- hoverEnabled: true
-
- // Set 'popupOpen' to show/hide the popup. The 'state' property is more
- // internal, and contains additional states used to protect the popup from
- // e.g. receiving mouse clicks while its about to hide etc.
- property bool popupOpen: false
-
- property bool desktopBehavior: true
- property int previousCurrentIndex: -1
- property alias model: listView.model
- property alias currentIndex: listView.currentIndex
- property string currentText: model && currentIndex >= 0 ? model.get(currentIndex).text : ""
-
- // buttonPressed will be true when the mouse press starts
- // while the popup is closed. At that point, this component can be
- // seen as a button, and not yet a popup menu:
- property bool buttonPressed: false
-
- property Component listItem
- property Component listHighlight
- property Component popupFrame
-
- property Item originalParent: parent
-
- onPopupOpenChanged: {
- if (popupFrameLoader.item === null)
- return;
- if (popupOpen) {
- var oldMouseX = mouseX
-
- // Reparent to root, so the popup stacks in front:
- originalParent = parent;
- var p = parent;
- while (p.parent != undefined)
- p = p.parent
- parent = p;
-
- previousCurrentIndex = currentIndex;
- positionPopup();
- popupFrameLoader.item.opacity = 1;
- if (oldMouseX === mouseX){
- // Work around bug: mouseX and mouseY does not immidiatly
- // update after reparenting and resizing the mouse area:
- var pos = originalParent.mapToItem(parent, mouseX, mouseY)
- highlightItemAt(pos.x, pos.y);
- } else {
- highlightItemAt(mouseX, mouseY);
- }
- listView.forceActiveFocus();
- state = "popupOpen"
- } else {
- popupFrameLoader.item.opacity = 0;
- popup.hideHighlight();
- if (popupFrameLoader.item.opacity !== 0)
- state = "popupClosed"
- }
- }
-
- Component.onCompleted: {
- // In case 'popupOpen' was set to 'true' before
- // 'popupFrameLoader' was finished, we open the popup now instead:
- if (popup.popupOpen){
- popup.popupOpen = false
- popup.popupOpen = true
- }
- }
-
- function highlightItemAt(posX, posY)
- {
- var mappedPos = mapToItem(listView.contentItem, posX, posY);
- var indexAt = listView.indexAt(mappedPos.x, mappedPos.y);
- if (indexAt == listView.highlightedIndex)
- return;
- if (indexAt >= 0) {
- listView.highlightedIndex = indexAt;
- } else {
- if(posY > listView.y+listView.height && listView.highlightedIndex+1 < listView.count ) {
- listView.highlightedIndex++;
- } else if(posY < listView.y && listView.highlightedIndex > 0) {
- listView.highlightedIndex--;
- } else if(posX < popupFrameLoader.x || posX > popupFrameLoader.x+popupFrameLoader.width) {
- popup.hideHighlight();
- }
- }
- }
-
- function hideHighlight() {
- listView.highlightedIndex = -1;
- listView.highlightedItem = null; // will trigger positionHighlight() what will hide the highlight
- }
-
- function positionPopup() {
- // Set initial values to top left corner of original parent:
- var globalPos = mapFromItem(originalParent, 0, 0);
- var newX = globalPos.x;
- var newY = globalPos.y
- var newW = originalParent.width;
- var newH = listView.contentHeight
-
- switch (popupFrameLoader.item.popupLocation) {
- case "center":
- // Show centered over original parent with respect to selected item:
- 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
- newY -= currentItemY;
- break;
- case "below":
- case "":
- // Show below original parent:
- newX -= popupFrameLoader.anchors.leftMargin;
- newY += originalParent.height - popupFrameLoader.anchors.topMargin;
- break;
- }
-
- // Ensure the popup is inside the window:
- if (newX < popupFrameLoader.anchors.leftMargin)
- newX = popupFrameLoader.anchors.leftMargin;
- else if (newX + newW > popup.width - popupFrameLoader.anchors.rightMargin)
- newX = popup.width - popupFrameLoader.anchors.rightMargin - newW;
-
- if (newY < popupFrameLoader.anchors.topMargin)
- newY = popupFrameLoader.anchors.topMargin;
- else if (newY + newH > popup.height - popupFrameLoader.anchors.bottomMargin)
- newY = popup.height - popupFrameLoader.anchors.bottomMargin - newH;
-
- // Todo: handle case when the list itself is larger than the window...
-
- listView.x = newX
- listView.y = newY
- listView.width = newW
- listView.height = newH
- }
-
- Loader {
- id: popupFrameLoader
- property alias styledItem: popup.originalParent
- 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
- onItemChanged: item.opacity = 0
- }
-
- ListView {
- id: listView
- focus: true
- opacity: popupFrameLoader.item.opacity
- 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
- }
- }
-
- 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 'index'
-
- Loader {
- id: delegateLoader
- property variant model: listView.model
- property alias index: itemDelegate.theIndex
- property Item styledItem: choiceList
- property bool highlighted: theIndex == listView.highlightedIndex
- property string itemText: popup.model.get(theIndex).text
- sourceComponent: listItem
- }
-
- 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) {
- listView.currentIndex = highlightedIndex;
- } else {
- listView.currentIndex = popup.previousCurrentIndex;
- }
-
- popup.popupOpen = false;
- } else if (event.key == Qt.Key_Escape) {
- listView.currentIndex = popup.previousCurrentIndex;
- popup.popupOpen = false;
- }
- event.accepted = true; // consume all keys while popout has focus
- }
-
- highlight: popup.listHighlight
- }
-
- Timer {
- // This is the time-out value for when we consider the
- // user doing a press'n'release, and not just a click to
- // open the popup:
- id: pressedTimer
- interval: 400 // Todo: fetch value from style object
- }
-
- onPressed: {
- if (state == "popupClosed") {
- // Show the popup:
- pressedTimer.running = true
- popup.popupOpen = true
- popup.buttonPressed = true
- }
- }
-
- onReleased: {
- if (state == "popupOpen" && pressedTimer.running === false) {
- // Either we have a 'new' click on the popup, or the user has
- // done a drag'n'release. In either case, the user has done a selection:
- var mappedPos = mapToItem(listView.contentItem, mouseX, mouseY);
- var indexAt = listView.indexAt(mappedPos.x, mappedPos.y);
- if(indexAt != -1)
- listView.currentIndex = indexAt;
- popup.popupOpen = false
- }
- popup.buttonPressed = false
- }
-
- onPositionChanged: {
- if (state == "popupOpen")
- popup.highlightItemAt(mouseX, mouseY)
- }
-
- states: [
- State {
- name: "popupClosed"
- when: popupFrameLoader.item.opacity === 0;
- StateChangeScript {
- script: parent = originalParent
- }
- }
- ]
-}
-
-
-
-
diff --git a/components/custom/qmldir b/components/custom/qmldir
index 8da1fd80..716e44fa 100644
--- a/components/custom/qmldir
+++ b/components/custom/qmldir
@@ -6,9 +6,9 @@ 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
Slider 1.0 Slider.qml
SpinBox 1.0 SpinBox.qml
TextField 1.0 TextField.qml
GroupBox 1.0 GroupBox.qml
+Splitter 1.0 Splitter.qml
diff --git a/components/private/ScrollAreaHelper.qml b/components/private/ScrollAreaHelper.qml
new file mode 100644
index 00000000..7a58d5df
--- /dev/null
+++ b/components/private/ScrollAreaHelper.qml
@@ -0,0 +1,83 @@
+import QtQuick 1.1
+import "../"
+
+WheelArea {
+ id: wheelarea
+
+ property alias horizontalScrollBar: hscrollbar
+ property alias verticalScrollBar: vscrollbar
+ property int macOffset: styleitem.style == "mac" ? 1 : 0
+ property bool blockUpdates: false
+ property int availableHeight : root.height - (hscrollbar.visible ? hscrollbar.height : 0)
+ property int availableWidth: root.width - vscrollbar.width
+
+ anchors.fill: parent
+ anchors.margins: frameWidth
+ horizontalMinimumValue: hscrollbar.minimumValue
+ horizontalMaximumValue: hscrollbar.maximumValue
+ verticalMinimumValue: vscrollbar.minimumValue
+ verticalMaximumValue: vscrollbar.maximumValue
+
+ onVerticalValueChanged: {
+ if (!blockUpdates)
+ verticalScrollBar.value = verticalValue
+ }
+
+ onHorizontalValueChanged: {
+ if (!blockUpdates)
+ horizontalScrollBar.value = horizontalValue
+ }
+
+ StyleItem {
+ // This is the filled corner between scrollbars
+ id: cornerFill
+ elementType: "scrollareacorner"
+ width: vscrollbar.width
+ anchors.right: parent.right
+ height: hscrollbar.height
+ anchors.bottom: parent.bottom
+ visible: hscrollbar.visible && vscrollbar.visible
+ }
+
+ ScrollBar {
+ id: hscrollbar
+ orientation: Qt.Horizontal
+ visible: contentWidth > availableWidth
+ maximumValue: contentWidth > availableWidth ? root.contentWidth - availableWidth : 0
+ minimumValue: 0
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: parent.macOffset
+ anchors.bottomMargin: -parent.macOffset
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: vscrollbar.visible ? vscrollbar.width -parent.macOffset: 0
+ onValueChanged: {
+ if (!blockUpdates) {
+ contentX = value
+ horizontalValue = value
+ }
+ }
+ }
+
+ ScrollBar {
+ id: vscrollbar
+ orientation: Qt.Vertical
+ // We cannot bind directly to tree.height due to binding loops so we have to redo the calculation here
+ visible: contentHeight > availableHeight
+ maximumValue: contentHeight > availableHeight ? root.contentHeight - availableHeight : 0
+ minimumValue: 0
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.topMargin: parent.macOffset
+ anchors.rightMargin: -parent.macOffset
+ anchors.bottomMargin: hscrollbar.visible ? hscrollbar.height - parent.macOffset : 0
+
+ onValueChanged: {
+ if (!blockUpdates) {
+ contentY = value
+ verticalValue = value
+ }
+ }
+ }
+}
diff --git a/components/qmldir b/components/qmldir
index ae9e9eff..000c0218 100644
--- a/components/qmldir
+++ b/components/qmldir
@@ -2,6 +2,7 @@ Slider 0.1 Slider.qml
SpinBox 0.1 SpinBox.qml
GroupBox 0.1 GroupBox.qml
Button 0.1 Button.qml
+Label 0.1 Label.qml
ToolBar 0.1 ToolBar.qml
TabFrame 0.1 TabFrame.qml
TabBar 0.1 TabBar.qml
@@ -9,7 +10,6 @@ Tab 0.1 Tab.qml
Frame 0.1 Frame.qml
ScrollArea 0.1 ScrollArea.qml
ScrollBar 0.1 ScrollBar.qml
-ChoiceList 0.1 ChoiceList.qml
ComboBox 0.1 ComboBox.qml
ToolButton 0.1 ToolButton.qml
TextArea 0.1 TextArea.qml
@@ -18,6 +18,7 @@ ProgressBar 0.1 ProgressBar.qml
ButtonRow 0.1 ButtonRow.qml
ButtonColumn 0.1 ButtonColumn.qml
SplitterRow 0.1 SplitterRow.qml
+SplitterColumn 0.1 SplitterColumn.qml
Dial 0.1 Dial.qml
TableView 0.1 TableView.qml
CheckBox 0.1 CheckBox.qml
@@ -26,3 +27,6 @@ plugin styleplugin plugin
TableColumn 0.1 TableColumn.qml
ContextMenu 0.1 ContextMenu.qml
MenuItem 0.1 MenuItem.qml
+Dialog 0.1 Dialog.qml
+StatusBar 0.1 StatusBar.qml
+ApplicationWindow 0.1 ApplicationWindow.qml