main.qml Example File
qmlbars/qml/qmlbars/main.qml
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import QtDataVisualization 1.1
import QtQuick.Window 2.0
import "."
Rectangle {
id: mainview
width: 1280
height: 1024
property int buttonLayoutHeight: 180;
state: Screen.width < Screen.height ? "portrait" : "landscape"
Data {
id: graphData
}
Axes {
id: graphAxes
}
property Bar3DSeries selectedSeries
selectedSeries: barSeries
function handleSelectionChange(series, position) {
if (position != series.invalidSelectionPosition) {
selectedSeries = series
}
var rowRole = series.dataProxy.rowLabels[position.x];
var colRole
if (barGraph.columnAxis === graphAxes.total)
colRole = "01";
else
colRole = series.dataProxy.columnLabels[position.y];
var checkTimestamp = rowRole + "-" + colRole
var currentRow = tableView.currentRow
if (currentRow === -1 || checkTimestamp !== graphData.model.get(currentRow).timestamp) {
var totalRows = tableView.rowCount;
for (var i = 0; i < totalRows; i++) {
var modelTimestamp = graphData.model.get(i).timestamp
if (modelTimestamp === checkTimestamp) {
tableView.currentRow = i
if (typeof tableView.selection != "undefined") {
tableView.selection.clear()
tableView.selection.select(i)
}
break
}
}
}
}
Item {
id: dataView
anchors.right: mainview.right;
anchors.bottom: mainview.bottom
Bars3D {
id: barGraph
width: dataView.width
height: dataView.height
shadowQuality: AbstractGraph3D.ShadowQualityMedium
selectionMode: AbstractGraph3D.SelectionItem
theme: Theme3D {
type: Theme3D.ThemeRetro
labelBorderEnabled: true
font.pointSize: 35
labelBackgroundEnabled: true
colorStyle: Theme3D.ColorStyleRangeGradient
singleHighlightGradient: customGradient
ColorGradient {
id: customGradient
ColorGradientStop { position: 1.0; color: "#FFFF00" }
ColorGradientStop { position: 0.0; color: "#808000" }
}
}
barThickness: 0.7
barSpacing: Qt.size(0.5, 0.5)
barSpacingRelative: false
scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh
columnAxis: graphAxes.column
rowAxis: graphAxes.row
valueAxis: graphAxes.value
Bar3DSeries {
id: secondarySeries
visible: false
itemLabelFormat: "Expenses, @colLabel, @rowLabel: -@valueLabel"
baseGradient: secondaryGradient
ItemModelBarDataProxy {
id: secondaryProxy
itemModel: graphData.model
rowRole: "timestamp"
columnRole: "timestamp"
valueRole: "expenses"
rowRolePattern: /^(\d\d\d\d).*$/
columnRolePattern: /^.*-(\d\d)$/
valueRolePattern: /-/
rowRoleReplace: "\\1"
columnRoleReplace: "\\1"
multiMatchBehavior: ItemModelBarDataProxy.MMBCumulative
}
ColorGradient {
id: secondaryGradient
ColorGradientStop { position: 1.0; color: "#FF0000" }
ColorGradientStop { position: 0.0; color: "#600000" }
}
onSelectedBarChanged: handleSelectionChange(secondarySeries, position)
}
Bar3DSeries {
id: barSeries
itemLabelFormat: "Income, @colLabel, @rowLabel: @valueLabel"
baseGradient: barGradient
ItemModelBarDataProxy {
id: modelProxy
itemModel: graphData.model
rowRole: "timestamp"
columnRole: "timestamp"
valueRole: "income"
rowRolePattern: /^(\d\d\d\d).*$/
columnRolePattern: /^.*-(\d\d)$/
rowRoleReplace: "\\1"
columnRoleReplace: "\\1"
multiMatchBehavior: ItemModelBarDataProxy.MMBCumulative
}
ColorGradient {
id: barGradient
ColorGradientStop { position: 1.0; color: "#00FF00" }
ColorGradientStop { position: 0.0; color: "#006000" }
}
onSelectedBarChanged: handleSelectionChange(barSeries, position)
}
}
}
TableView {
id: tableView
anchors.top: parent.top
anchors.left: parent.left
TableViewColumn{ role: "timestamp" ; title: "Month" ; width: tableView.width / 2 }
TableViewColumn{ role: "expenses" ; title: "Expenses" ; width: tableView.width / 4 }
TableViewColumn{ role: "income" ; title: "Income" ; width: tableView.width / 4 }
itemDelegate: Item {
Text {
id: delegateText
anchors.verticalCenter: parent.verticalCenter
width: parent.width
anchors.leftMargin: 4
anchors.left: parent.left
anchors.right: parent.right
color: styleData.textColor
elide: styleData.elideMode
text: customText
horizontalAlignment: styleData.textAlignment
property string originalText: styleData.value
property string customText
onOriginalTextChanged: {
if (styleData.column === 0) {
if (delegateText.originalText !== "") {
var pattern = /(\d\d\d\d)-(\d\d)/
var matches = pattern.exec(delegateText.originalText)
var colIndex = parseInt(matches[2], 10) - 1
delegateText.customText = matches[1] + " - " + graphAxes.column.labels[colIndex]
}
} else {
delegateText.customText = originalText
}
}
}
}
model: graphData.model
onCurrentRowChanged: {
var timestamp = graphData.model.get(currentRow).timestamp
var pattern = /(\d\d\d\d)-(\d\d)/
var matches = pattern.exec(timestamp)
var rowIndex = modelProxy.rowCategoryIndex(matches[1])
var colIndex
if (barGraph.columnAxis === graphAxes.total)
colIndex = 0
else
colIndex = modelProxy.columnCategoryIndex(matches[2])
if (selectedSeries.visible)
mainview.selectedSeries.selectedBar = Qt.point(rowIndex, colIndex)
else if (barSeries.visible)
barSeries.selectedBar = Qt.point(rowIndex, colIndex)
else
secondarySeries.selectedBar = Qt.point(rowIndex, colIndex)
}
}
ColumnLayout {
id: controlLayout
spacing: 0
Button {
id: changeDataButton
Layout.fillWidth: true
Layout.fillHeight: true
text: "Show 2010 - 2012"
clip: true
onClicked: {
if (text === "Show yearly totals") {
modelProxy.autoRowCategories = true
secondaryProxy.autoRowCategories = true
modelProxy.columnRolePattern = /^.*$/
secondaryProxy.columnRolePattern = /^.*$/
graphAxes.value.autoAdjustRange = true
barGraph.columnAxis = graphAxes.total
text = "Show all years"
} else if (text === "Show all years") {
modelProxy.autoRowCategories = true
secondaryProxy.autoRowCategories = true
modelProxy.columnRolePattern = /^.*-(\d\d)$/
secondaryProxy.columnRolePattern = /^.*-(\d\d)$/
graphAxes.value.min = 0
graphAxes.value.max = 35
barGraph.columnAxis = graphAxes.column
text = "Show 2010 - 2012"
} else {
modelProxy.autoRowCategories = false
secondaryProxy.autoRowCategories = false
modelProxy.rowCategories = ["2010", "2011", "2012"]
secondaryProxy.rowCategories = ["2010", "2011", "2012"]
text = "Show yearly totals"
}
}
}
Button {
id: shadowToggle
Layout.fillWidth: true
Layout.fillHeight: true
text: barGraph.shadowsSupported ? "Hide Shadows" : "Shadows not supported"
clip: true
enabled: barGraph.shadowsSupported
onClicked: {
if (barGraph.shadowQuality == AbstractGraph3D.ShadowQualityNone) {
barGraph.shadowQuality = AbstractGraph3D.ShadowQualityMedium;
text = "Hide Shadows"
} else {
barGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
text = "Show Shadows"
}
}
}
Button {
id: seriesToggle
Layout.fillWidth: true
Layout.fillHeight: true
text: "Show Expenses"
clip: true
onClicked: {
if (text === "Show Expenses") {
barSeries.visible = false
secondarySeries.visible = true
barGraph.valueAxis.labelFormat = "-%.2f M\u20AC"
secondarySeries.itemLabelFormat = "Expenses, @colLabel, @rowLabel: @valueLabel"
text = "Show Both"
} else if (text === "Show Both") {
barSeries.visible = true
barGraph.valueAxis.labelFormat = "%.2f M\u20AC"
secondarySeries.itemLabelFormat = "Expenses, @colLabel, @rowLabel: -@valueLabel"
text = "Show Income"
} else {
secondarySeries.visible = false
text = "Show Expenses"
}
}
}
}
states: [
State {
name: "landscape"
PropertyChanges {
target: dataView
width: mainview.width / 4 * 3
height: mainview.height
}
PropertyChanges {
target: tableView
height: mainview.height - buttonLayoutHeight
anchors.right: dataView.left
anchors.left: mainview.left
anchors.bottom: undefined
}
PropertyChanges {
target: controlLayout
width: mainview.width / 4
height: buttonLayoutHeight
anchors.top: tableView.bottom
anchors.bottom: mainview.bottom
anchors.left: mainview.left
anchors.right: dataView.left
}
},
State {
name: "portrait"
PropertyChanges {
target: dataView
width: mainview.height / 4 * 3
height: mainview.width
}
PropertyChanges {
target: tableView
height: mainview.width
anchors.right: controlLayout.left
anchors.left: mainview.left
anchors.bottom: dataView.top
}
PropertyChanges {
target: controlLayout
width: mainview.height / 4
height: mainview.width / 4
anchors.top: mainview.top
anchors.bottom: dataView.top
anchors.left: undefined
anchors.right: mainview.right
}
}
]
}