QuickGraphLib 0.1.0a0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- QuickGraphLib/AntialiasingContainer.qml +18 -0
- QuickGraphLib/Axis.qml +227 -0
- QuickGraphLib/GraphArea.qml +54 -0
- QuickGraphLib/GraphItems/AxHLine.qml +25 -0
- QuickGraphLib/GraphItems/AxHSpan.qml +28 -0
- QuickGraphLib/GraphItems/AxVLine.qml +25 -0
- QuickGraphLib/GraphItems/AxVSpan.qml +28 -0
- QuickGraphLib/GraphItems/BasicLegend.qml +29 -0
- QuickGraphLib/GraphItems/BasicLegendItem.qml +54 -0
- QuickGraphLib/GraphItems/Contour.qml +33 -0
- QuickGraphLib/GraphItems/GraphItemDragHandler.qml +39 -0
- QuickGraphLib/GraphItems/Grid.qml +58 -0
- QuickGraphLib/GraphItems/Histogram.qml +50 -0
- QuickGraphLib/GraphItems/Line.qml +58 -0
- QuickGraphLib/GraphItems/Marker.qml +28 -0
- QuickGraphLib/GraphItems/qmldir +16 -0
- QuickGraphLib/Helpers.js +167 -0
- QuickGraphLib/PreFabs/XYAxes.qml +103 -0
- QuickGraphLib/PreFabs/qmldir +5 -0
- QuickGraphLib/ScalingContainer.qml +38 -0
- QuickGraphLib/ZoomPanHandler.qml +78 -0
- QuickGraphLib/qmldir +10 -0
- QuickGraphLib-0.1.0a0.dist-info/LICENCE +21 -0
- QuickGraphLib-0.1.0a0.dist-info/METADATA +73 -0
- QuickGraphLib-0.1.0a0.dist-info/RECORD +32 -0
- QuickGraphLib-0.1.0a0.dist-info/WHEEL +5 -0
- QuickGraphLib-0.1.0a0.dist-info/top_level.txt +2 -0
- quickgraphlib_helpers/__init__.py +4 -0
- quickgraphlib_helpers/consts.py +6 -0
- quickgraphlib_helpers/contours.py +79 -0
- quickgraphlib_helpers/export.py +167 -0
- quickgraphlib_helpers/py.typed +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import QtQuick
|
|
5
|
+
import QtQuick.Shapes as QQS
|
|
6
|
+
|
|
7
|
+
/*!
|
|
8
|
+
\qmltype Line
|
|
9
|
+
\inqmlmodule QuickGraphLib.GraphItems
|
|
10
|
+
\inherits QtQuick::Shapes::ShapePath
|
|
11
|
+
\brief Displays a line graph.
|
|
12
|
+
|
|
13
|
+
Graph a line using a list of X,Y points. The style of the line can be adjusted using the \l {ShapePath::strokeColor} {strokeColor} and \l {ShapePath::strokeWidth} {strokeWidth} properties.
|
|
14
|
+
|
|
15
|
+
\qml
|
|
16
|
+
GraphArea {
|
|
17
|
+
id: grapharea
|
|
18
|
+
viewRect: Qt.rect(-20, -1.1, 760, 2.2)
|
|
19
|
+
|
|
20
|
+
Line {
|
|
21
|
+
dataTransform: grapharea.dataTransform
|
|
22
|
+
path: Helpers.linspace(0, 720, 100).map(x => Qt.point(x, Math.sin(x / 180 * Math.PI)))
|
|
23
|
+
strokeColor: "red"
|
|
24
|
+
strokeWidth: 2
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
\endqml
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
QQS.ShapePath {
|
|
31
|
+
id: root
|
|
32
|
+
|
|
33
|
+
/*!
|
|
34
|
+
Transform from data coordinates to pixel coordinates (this is usually provided by a GraphArea).
|
|
35
|
+
|
|
36
|
+
\qmlproperty list<point> Line::path
|
|
37
|
+
\omit
|
|
38
|
+
QDoc seems to read list<x> as x, so override the type of path here.
|
|
39
|
+
\endomit
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
required property matrix4x4 dataTransform
|
|
43
|
+
|
|
44
|
+
/*!
|
|
45
|
+
Points to graph. Each point is a \l point (containing x and y coordinates) in the data space.
|
|
46
|
+
*/
|
|
47
|
+
required property list<point> path
|
|
48
|
+
|
|
49
|
+
capStyle: QQS.ShapePath.RoundCap
|
|
50
|
+
fillColor: "transparent"
|
|
51
|
+
joinStyle: QQS.ShapePath.RoundJoin
|
|
52
|
+
startX: root.path[0].x
|
|
53
|
+
startY: root.path[0].y
|
|
54
|
+
|
|
55
|
+
PathPolyline {
|
|
56
|
+
path: root.path.map(p => root.dataTransform.map(p))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import QtQuick
|
|
5
|
+
|
|
6
|
+
/*!
|
|
7
|
+
\qmltype Marker
|
|
8
|
+
\inqmlmodule QuickGraphLib.GraphItems
|
|
9
|
+
\inherits QtQuick::Rectangle
|
|
10
|
+
\brief Displays a circular marker.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
Rectangle {
|
|
14
|
+
id: root
|
|
15
|
+
|
|
16
|
+
/*! TODO */
|
|
17
|
+
required property matrix4x4 dataTransform
|
|
18
|
+
readonly property point pixelPosition: root.dataTransform.map(position)
|
|
19
|
+
/*! TODO */
|
|
20
|
+
required property point position
|
|
21
|
+
|
|
22
|
+
border.width: 0
|
|
23
|
+
height: width
|
|
24
|
+
radius: width / 2
|
|
25
|
+
width: 5
|
|
26
|
+
x: pixelPosition.x - width / 2
|
|
27
|
+
y: pixelPosition.y - width / 2
|
|
28
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
module QuickGraphLib.GraphItems
|
|
5
|
+
AxHLine AxHLine.qml
|
|
6
|
+
AxHSpan AxHSpan.qml
|
|
7
|
+
AxVLine AxVLine.qml
|
|
8
|
+
AxVSpan AxVSpan.qml
|
|
9
|
+
BasicLegend BasicLegend.qml
|
|
10
|
+
BasicLegendItem BasicLegendItem.qml
|
|
11
|
+
Contour Contour.qml
|
|
12
|
+
GraphItemDragHandler GraphItemDragHandler.qml
|
|
13
|
+
Grid Grid.qml
|
|
14
|
+
Histogram Histogram.qml
|
|
15
|
+
Line Line.qml
|
|
16
|
+
Marker Marker.qml
|
QuickGraphLib/Helpers.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
/*!
|
|
5
|
+
\qmltype Helpers
|
|
6
|
+
\inqmlmodule QuickGraphLib
|
|
7
|
+
\brief Helper functions for building graphs.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Indentation due to VSCode's formatter...
|
|
11
|
+
.import QtQuick as QQ
|
|
12
|
+
.import QtQuick.Shapes as QQS
|
|
13
|
+
|
|
14
|
+
function linspace(min, max, num) {
|
|
15
|
+
/*!
|
|
16
|
+
\qmlmethod list<double> Helpers::linspace(double min, double max, int num)
|
|
17
|
+
|
|
18
|
+
Returns a list of \a num values equally spaced from \a min and \a max (inclusive).
|
|
19
|
+
*/
|
|
20
|
+
return Array.from((new Array(num)).keys(), i => i / (num - 1) * (max - min) + min);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
function range(min, max, step) {
|
|
25
|
+
/*!
|
|
26
|
+
\qmlmethod list<int> Helpers::range(int min, int max, int step = 1)
|
|
27
|
+
|
|
28
|
+
Returns a list of values from \a min to \a max (exclusive) with a gap of \a step between each one.
|
|
29
|
+
*/
|
|
30
|
+
step = step ?? 1;
|
|
31
|
+
let num = Math.max(0, Math.floor((max - min) / step));
|
|
32
|
+
return Array.from((new Array(num)).keys(), i => min + step * i);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function tickLocator(min, max, maxNum) {
|
|
36
|
+
/*!
|
|
37
|
+
\qmlmethod list<double> Helpers::tickLocator(double min, double max, int maxNum)
|
|
38
|
+
|
|
39
|
+
Returns a list of at most \a maxNum nice tick locations values equally spaced between \a min and \a max.
|
|
40
|
+
*/
|
|
41
|
+
if (min == max || !isFinite(min) || !isFinite(max) || maxNum == 0) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
let steps = [0.2, 0.25, 0.5, 1];
|
|
45
|
+
let approxTickSpacing = (max - min) / (maxNum - 1);
|
|
46
|
+
let magnitude = Math.ceil(Math.log10(approxTickSpacing));
|
|
47
|
+
let normedTickSpacing = approxTickSpacing / Math.pow(10, magnitude);
|
|
48
|
+
let tickSpacing = steps.find(x => x >= normedTickSpacing) * Math.pow(10, magnitude);
|
|
49
|
+
let lower = Math.ceil(min / tickSpacing - 1e-4) * tickSpacing;
|
|
50
|
+
let upper = Math.floor(max / tickSpacing + 1e-4) * tickSpacing;
|
|
51
|
+
let numTicks = Math.round((upper - lower) / tickSpacing + 1);
|
|
52
|
+
console.assert(numTicks <= maxNum, "Calculated too many ticks");
|
|
53
|
+
return Array.from((new Array(numTicks)).keys(), i => lower + i * tickSpacing);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function _exportTransform(t) {
|
|
57
|
+
if (t instanceof QQ.Translate) {
|
|
58
|
+
return {
|
|
59
|
+
"type": "translate",
|
|
60
|
+
"x": t.x,
|
|
61
|
+
"y": t.y
|
|
62
|
+
}
|
|
63
|
+
} else if (t instanceof QQ.Rotation) {
|
|
64
|
+
return {
|
|
65
|
+
"type": "rotation",
|
|
66
|
+
"angle": t.angle,
|
|
67
|
+
"origin": t.origin
|
|
68
|
+
}
|
|
69
|
+
} else if (t instanceof QQ.Scale) {
|
|
70
|
+
return {
|
|
71
|
+
"type": "scale",
|
|
72
|
+
"xScale": t.xScale,
|
|
73
|
+
"yScale": t.yScale,
|
|
74
|
+
"origin": t.origin
|
|
75
|
+
}
|
|
76
|
+
} else if (t instanceof QQ.Matrix4x4) {
|
|
77
|
+
return {
|
|
78
|
+
"type": "matrix4x4",
|
|
79
|
+
"matrix": t.matrix
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function _exportGradient(g) {
|
|
85
|
+
if (g === null) {
|
|
86
|
+
return null
|
|
87
|
+
} else if (g instanceof QQS.LinearGradient) {
|
|
88
|
+
return {
|
|
89
|
+
"type": "lineargradient",
|
|
90
|
+
"x1": g.x1,
|
|
91
|
+
"x2": g.x2,
|
|
92
|
+
"y1": g.y1,
|
|
93
|
+
"y2": g.y2,
|
|
94
|
+
"stops": g.stops.map(s => ({
|
|
95
|
+
color: s.color, position: s.position
|
|
96
|
+
}))
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function exportData(obj) {
|
|
102
|
+
/*!
|
|
103
|
+
\qmlmethod var Helpers::exportData(Item obj)
|
|
104
|
+
|
|
105
|
+
Returns information on \a obj which will allow it to be rendered to SVG/PNG using the Python helpers.
|
|
106
|
+
|
|
107
|
+
\note Only some QML elements are supported by this export method (e.g. \l {QtQuick::Rectangle} {Rectangle}, PathPolyline).
|
|
108
|
+
Other elements will be rendered incorrectly or not at all. If an element is not rendered correctly,
|
|
109
|
+
create a new issue and we'll see if it can be added.
|
|
110
|
+
|
|
111
|
+
\sa ExportHelper::exportToSvg, ExportHelper::exportToPng
|
|
112
|
+
*/
|
|
113
|
+
let data = { "type": null, "js": obj.toString() };
|
|
114
|
+
if (obj instanceof QQ.Item) {
|
|
115
|
+
data.x = obj.x;
|
|
116
|
+
data.y = obj.y;
|
|
117
|
+
data.z = obj.z;
|
|
118
|
+
data.width = obj.width;
|
|
119
|
+
data.height = obj.height;
|
|
120
|
+
data.children = obj.data.map(exportData);
|
|
121
|
+
data.clip = obj.clip;
|
|
122
|
+
data.transform = obj.transform.map(_exportTransform);
|
|
123
|
+
data.opacity = obj.opacity;
|
|
124
|
+
data.visible = obj.visible;
|
|
125
|
+
|
|
126
|
+
if (obj instanceof QQ.Text) {
|
|
127
|
+
data.type = "text";
|
|
128
|
+
data.text = obj.text;
|
|
129
|
+
data.color = obj.color;
|
|
130
|
+
data.fontFamily = obj.font.family;
|
|
131
|
+
data.fontSize = obj.font.pixelSize;
|
|
132
|
+
data.fontWeight = obj.font.weight;
|
|
133
|
+
}
|
|
134
|
+
else if (obj instanceof QQ.Rectangle) {
|
|
135
|
+
data.type = "rectangle";
|
|
136
|
+
data.border_color = obj.border.color;
|
|
137
|
+
data.border_width = obj.border.width;
|
|
138
|
+
data.color = obj.color;
|
|
139
|
+
data.radius = obj.radius;
|
|
140
|
+
data.gradient = _exportGradient(obj.gradient);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else if (obj instanceof QQS.ShapePath) {
|
|
144
|
+
data.type = "shape_path";
|
|
145
|
+
data.elements = obj.pathElements.map(exportData);
|
|
146
|
+
data.capStyle = obj.capStyle;
|
|
147
|
+
data.dashOffset = obj.dashOffset;
|
|
148
|
+
data.dashPattern = obj.dashPattern.map(x => x);
|
|
149
|
+
data.fillColor = obj.fillColor;
|
|
150
|
+
data.fillGradient = _exportGradient(obj.fillGradient);
|
|
151
|
+
data.fillRule = obj.fillRule;
|
|
152
|
+
data.joinStyle = obj.joinStyle;
|
|
153
|
+
data.miterLimit = obj.miterLimit;
|
|
154
|
+
data.strokeColor = obj.strokeColor;
|
|
155
|
+
data.strokeStyle = obj.strokeStyle;
|
|
156
|
+
data.strokeWidth = obj.strokeWidth;
|
|
157
|
+
}
|
|
158
|
+
else if (obj instanceof QQ.PathPolyline) {
|
|
159
|
+
data.type = "polyline";
|
|
160
|
+
data.path = obj.path;
|
|
161
|
+
}
|
|
162
|
+
else if (obj instanceof QQ.PathMultiline) {
|
|
163
|
+
data.type = "multiline";
|
|
164
|
+
data.paths = obj.paths;
|
|
165
|
+
}
|
|
166
|
+
return data;
|
|
167
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import QtQuick
|
|
5
|
+
import QtQuick.Layouts as QQL
|
|
6
|
+
import QuickGraphLib as QuickGraphLib
|
|
7
|
+
import QuickGraphLib.GraphItems as QGLGraphItems
|
|
8
|
+
|
|
9
|
+
/*!
|
|
10
|
+
\qmltype Line
|
|
11
|
+
\inqmlmodule QuickGraphLib.PreFabs
|
|
12
|
+
\inherits QuickGraphLib::AntialiasingContainer
|
|
13
|
+
\brief Displays an XY axis with a grid.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
QuickGraphLib.AntialiasingContainer {
|
|
17
|
+
id: root
|
|
18
|
+
|
|
19
|
+
/*! TODO */
|
|
20
|
+
property alias axes: axes
|
|
21
|
+
/*! TODO */
|
|
22
|
+
property alias dataTransform: grapharea.dataTransform
|
|
23
|
+
/*! TODO */
|
|
24
|
+
default property alias graphChildren: grapharea.data
|
|
25
|
+
/*! TODO */
|
|
26
|
+
property alias grapharea: grapharea
|
|
27
|
+
/*! TODO */
|
|
28
|
+
property int numXTicks: 11
|
|
29
|
+
/*! TODO */
|
|
30
|
+
property int numYTicks: 11
|
|
31
|
+
/*! TODO */
|
|
32
|
+
property bool showXTickLabels: true
|
|
33
|
+
/*! TODO */
|
|
34
|
+
property bool showYTickLabels: true
|
|
35
|
+
/*! TODO */
|
|
36
|
+
property alias title: titleLabel.text
|
|
37
|
+
/*! TODO */
|
|
38
|
+
required property rect viewRect
|
|
39
|
+
/*! TODO */
|
|
40
|
+
property alias xLabel: xAxis.label
|
|
41
|
+
/*! TODO */
|
|
42
|
+
property alias yLabel: yAxis.label
|
|
43
|
+
|
|
44
|
+
QQL.GridLayout {
|
|
45
|
+
id: axes
|
|
46
|
+
|
|
47
|
+
anchors.bottomMargin: 4
|
|
48
|
+
anchors.fill: parent
|
|
49
|
+
anchors.leftMargin: 15
|
|
50
|
+
anchors.rightMargin: 15
|
|
51
|
+
anchors.topMargin: 4
|
|
52
|
+
columnSpacing: 0
|
|
53
|
+
columns: 2
|
|
54
|
+
rowSpacing: 0
|
|
55
|
+
|
|
56
|
+
Text {
|
|
57
|
+
id: titleLabel
|
|
58
|
+
|
|
59
|
+
QQL.Layout.alignment: Qt.AlignCenter
|
|
60
|
+
QQL.Layout.columnSpan: 2
|
|
61
|
+
visible: text != ""
|
|
62
|
+
}
|
|
63
|
+
QuickGraphLib.Axis {
|
|
64
|
+
id: yAxis
|
|
65
|
+
|
|
66
|
+
QQL.Layout.fillHeight: true
|
|
67
|
+
dataTransform: grapharea.dataTransform
|
|
68
|
+
direction: QuickGraphLib.Axis.Direction.Left
|
|
69
|
+
showTickLabels: root.showYTickLabels
|
|
70
|
+
ticks: grid.yTicks
|
|
71
|
+
}
|
|
72
|
+
QuickGraphLib.GraphArea {
|
|
73
|
+
id: grapharea
|
|
74
|
+
|
|
75
|
+
QQL.Layout.fillHeight: true
|
|
76
|
+
QQL.Layout.fillWidth: true
|
|
77
|
+
viewRect: root.viewRect
|
|
78
|
+
|
|
79
|
+
QGLGraphItems.Grid {
|
|
80
|
+
id: grid
|
|
81
|
+
|
|
82
|
+
dataTransform: grapharea.dataTransform
|
|
83
|
+
parentHeight: grapharea.height
|
|
84
|
+
parentWidth: grapharea.width
|
|
85
|
+
strokeColor: "#11000000"
|
|
86
|
+
strokeWidth: 1
|
|
87
|
+
xTicks: QuickGraphLib.Helpers.tickLocator(grapharea.effectiveViewRect.x, grapharea.effectiveViewRect.x + grapharea.effectiveViewRect.width, root.numXTicks)
|
|
88
|
+
yTicks: QuickGraphLib.Helpers.tickLocator(grapharea.effectiveViewRect.y, grapharea.effectiveViewRect.y + grapharea.effectiveViewRect.height, root.numYTicks)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
Item {
|
|
92
|
+
}
|
|
93
|
+
QuickGraphLib.Axis {
|
|
94
|
+
id: xAxis
|
|
95
|
+
|
|
96
|
+
QQL.Layout.fillWidth: true
|
|
97
|
+
dataTransform: grapharea.dataTransform
|
|
98
|
+
direction: QuickGraphLib.Axis.Direction.Bottom
|
|
99
|
+
showTickLabels: root.showXTickLabels
|
|
100
|
+
ticks: grid.xTicks
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import QtQuick
|
|
5
|
+
|
|
6
|
+
/*!
|
|
7
|
+
\qmltype ScalingContainer
|
|
8
|
+
\inqmlmodule QuickGraphLib
|
|
9
|
+
\inherits AntialiasingContainer
|
|
10
|
+
\brief Scales it's contents while preserving the aspect ratio.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
AntialiasingContainer {
|
|
14
|
+
id: container
|
|
15
|
+
|
|
16
|
+
/*! TODO */
|
|
17
|
+
default property alias contentChildren: graph.children
|
|
18
|
+
/*! TODO */
|
|
19
|
+
property alias contentHeight: graph.height
|
|
20
|
+
/*! TODO */
|
|
21
|
+
property alias contentWidth: graph.width
|
|
22
|
+
|
|
23
|
+
implicitHeight: 100
|
|
24
|
+
implicitWidth: 100
|
|
25
|
+
|
|
26
|
+
Item {
|
|
27
|
+
id: graph
|
|
28
|
+
|
|
29
|
+
anchors.centerIn: parent
|
|
30
|
+
|
|
31
|
+
transform: Scale {
|
|
32
|
+
origin.x: graph.width / 2
|
|
33
|
+
origin.y: graph.height / 2
|
|
34
|
+
xScale: Math.min(container.width / graph.width, container.height / graph.height)
|
|
35
|
+
yScale: Math.min(container.width / graph.width, container.height / graph.height)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import QtQuick
|
|
5
|
+
|
|
6
|
+
/*!
|
|
7
|
+
\qmltype ZoomPanHandler
|
|
8
|
+
\inqmlmodule QuickGraphLib
|
|
9
|
+
\inherits QtQuick::PinchArea
|
|
10
|
+
\brief Pinch/drag handling for graph or image zoom/pan interactions.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
PinchArea {
|
|
14
|
+
id: root
|
|
15
|
+
|
|
16
|
+
/*! TODO */
|
|
17
|
+
property matrix4x4 baseTransform
|
|
18
|
+
/*! TODO */
|
|
19
|
+
property bool limitMovement: true
|
|
20
|
+
/*! TODO */
|
|
21
|
+
property size maxScale: Qt.size(10, 10)
|
|
22
|
+
/*! TODO */
|
|
23
|
+
property size minScale: Qt.size(1, 1)
|
|
24
|
+
/*! TODO */
|
|
25
|
+
readonly property matrix4x4 viewTransform: Qt.matrix4x4(baseTransform.m11, baseTransform.m12, baseTransform.m13, baseTransform.m14 * width, baseTransform.m21, baseTransform.m22, baseTransform.m23, baseTransform.m24 * height, baseTransform.m31, baseTransform.m32, baseTransform.m33, baseTransform.m34, baseTransform.m41, baseTransform.m42, baseTransform.m43, baseTransform.m44)
|
|
26
|
+
/*! TODO */
|
|
27
|
+
property double wheelZoomFactor: 1.05
|
|
28
|
+
|
|
29
|
+
function _applyLimitedMovement() {
|
|
30
|
+
if (limitMovement) {
|
|
31
|
+
// X bounds
|
|
32
|
+
baseTransform.m14 = Math.min(0, Math.max(1 - baseTransform.m11, baseTransform.m14));
|
|
33
|
+
// Y bounds
|
|
34
|
+
baseTransform.m24 = Math.min(0, Math.max(1 - baseTransform.m22, baseTransform.m24));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function _move(amount: vector3d) {
|
|
38
|
+
let change = Qt.matrix4x4();
|
|
39
|
+
change.translate(amount);
|
|
40
|
+
baseTransform = change.times(baseTransform);
|
|
41
|
+
_applyLimitedMovement();
|
|
42
|
+
}
|
|
43
|
+
function _zoom(center: vector3d, amount: double) {
|
|
44
|
+
let change = Qt.matrix4x4();
|
|
45
|
+
change.translate(center);
|
|
46
|
+
let xScale = Math.min(Math.max(baseTransform.m11 * amount, minScale.width), maxScale.width) / baseTransform.m11;
|
|
47
|
+
let yScale = Math.min(Math.max(baseTransform.m22 * amount, minScale.height), maxScale.height) / baseTransform.m22;
|
|
48
|
+
change.scale(xScale, yScale, 1);
|
|
49
|
+
change.translate(center.times(-1));
|
|
50
|
+
baseTransform = change.times(baseTransform);
|
|
51
|
+
_applyLimitedMovement();
|
|
52
|
+
}
|
|
53
|
+
function reset() {
|
|
54
|
+
baseTransform = Qt.matrix4x4();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
onPinchUpdated: pinch => root._zoom(Qt.vector3d(pinch.startCenter.x / width, pinch.startCenter.y / height, 0), pinch.scale / pinch.previousScale)
|
|
58
|
+
|
|
59
|
+
MouseArea {
|
|
60
|
+
id: dragArea
|
|
61
|
+
|
|
62
|
+
property vector3d prevPosition
|
|
63
|
+
|
|
64
|
+
anchors.fill: parent
|
|
65
|
+
drag.filterChildren: true
|
|
66
|
+
hoverEnabled: true
|
|
67
|
+
|
|
68
|
+
onPositionChanged: mouse => {
|
|
69
|
+
if (pressed) {
|
|
70
|
+
let newPosition = Qt.vector3d(mouse.x / width, mouse.y / height, 0);
|
|
71
|
+
root._move(newPosition.minus(prevPosition));
|
|
72
|
+
prevPosition = newPosition;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
onPressed: prevPosition = Qt.vector3d(mouseX / width, mouseY / height, 0)
|
|
76
|
+
onWheel: wheel => root._zoom(Qt.vector3d(mouseX / width, mouseY / height, 0), Math.pow(root.wheelZoomFactor, wheel.angleDelta.y / 15))
|
|
77
|
+
}
|
|
78
|
+
}
|
QuickGraphLib/qmldir
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
module QuickGraphLib
|
|
5
|
+
AntialiasingContainer AntialiasingContainer.qml
|
|
6
|
+
Axis Axis.qml
|
|
7
|
+
Helpers 1.0 Helpers.js
|
|
8
|
+
GraphArea GraphArea.qml
|
|
9
|
+
ScalingContainer ScalingContainer.qml
|
|
10
|
+
ZoomPanHandler ZoomPanHandler.qml
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: QuickGraphLib
|
|
3
|
+
Version: 0.1.0a0
|
|
4
|
+
Summary: A scientific graphing library for QtQuick
|
|
5
|
+
Author-email: Matthew Joyce <matthew.joyce@refeyn.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2024 Matthew Joyce and other QuickGraphLib contributors
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
Project-URL: Homepage, https://github.com/refeyn/QuickGraphLib
|
|
28
|
+
Project-URL: Issues, https://github.com/refeyn/QuickGraphLib/issues
|
|
29
|
+
Project-URL: Source, https://github.com/refeyn/QuickGraphLib
|
|
30
|
+
Classifier: Development Status :: 3 - Alpha
|
|
31
|
+
Classifier: Environment :: X11 Applications :: Qt
|
|
32
|
+
Classifier: Intended Audience :: Science/Research
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Operating System :: OS Independent
|
|
35
|
+
Classifier: Programming Language :: Python
|
|
36
|
+
Classifier: Topic :: Multimedia :: Graphics :: Presentation
|
|
37
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
38
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
39
|
+
Classifier: Typing :: Typed
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
License-File: LICENCE
|
|
42
|
+
Requires-Dist: PySide6
|
|
43
|
+
Requires-Dist: contourpy
|
|
44
|
+
Provides-Extra: analyse
|
|
45
|
+
Requires-Dist: black ; extra == 'analyse'
|
|
46
|
+
Requires-Dist: pylint ; extra == 'analyse'
|
|
47
|
+
Requires-Dist: mypy ; extra == 'analyse'
|
|
48
|
+
Requires-Dist: pre-commit ; extra == 'analyse'
|
|
49
|
+
Requires-Dist: lxml ; extra == 'analyse'
|
|
50
|
+
Requires-Dist: pytest ; extra == 'analyse'
|
|
51
|
+
Requires-Dist: pytest-cov ; extra == 'analyse'
|
|
52
|
+
|
|
53
|
+
# QuickGraphLib
|
|
54
|
+
|
|
55
|
+
A scientific graphing library for [QtQuick](https://doc.qt.io/qt-6/qtquick-index.html) using Qt6.
|
|
56
|
+
|
|
57
|
+
Key advantages:
|
|
58
|
+
|
|
59
|
+
- Written in pure QML (with some optional Python helpers), so it can be used in both C++ and Python projects
|
|
60
|
+
- QtQuick's hardware-based rendering makes this library render very fast
|
|
61
|
+
- Support for line graphs, histograms, contour plots and more
|
|
62
|
+
- Interactivity supported natively though declarative bindings and QtQuick
|
|
63
|
+
- Support for PNG and SVG export
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
The example gallery can be run using (provided the Python environment has [PySide6](https://pypi.org/project/PySide6/) and [contourpy](https://pypi.org/project/contourpy/) installed):
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python examples\gallery.py
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
<p align="center"><img src="./examples/ExampleGallery.png" width="80%"></p>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
QuickGraphLib/AntialiasingContainer.qml,sha256=rwY_q8BcNFvVWkx7vwCgHx2qgqvXJiyi5aaCpjJnxqI,459
|
|
2
|
+
QuickGraphLib/Axis.qml,sha256=42F2zPiAvqCoHsJZki_4KOPG8Cyb7N3qmVIUzHHIJYc,7198
|
|
3
|
+
QuickGraphLib/GraphArea.qml,sha256=WPwwsKFxvZWbZf6r6QIND8pIc2P_1R_Dcwe3dRGJeXA,1877
|
|
4
|
+
QuickGraphLib/Helpers.js,sha256=_NRRQssV1QAN2rGQsufa2BPwi8Sb1aq6PcNoQ9ZJWoU,5836
|
|
5
|
+
QuickGraphLib/ScalingContainer.qml,sha256=Vb5VF_9M5KK4iTvKGGcOmnV3EuAEWI3nfzghHI-yr7M,1019
|
|
6
|
+
QuickGraphLib/ZoomPanHandler.qml,sha256=S23_pXHqwy6mPbVPMWbIF5XlH_RO33Nw5CGzaFq0iw8,3081
|
|
7
|
+
QuickGraphLib/qmldir,sha256=6bdW8Uyv_Krun8Mylv0SClVtJNGB6pQ1ThDP8eCZDBE,338
|
|
8
|
+
QuickGraphLib/GraphItems/AxHLine.qml,sha256=EiKeHH92uPFQJgKlSz8XdLsrFUjvJ-XBat2Nwe0M00E,609
|
|
9
|
+
QuickGraphLib/GraphItems/AxHSpan.qml,sha256=sR8uRIb91bbcZ-BMm8RszbEjKjA34ZTn-Nk3T-J-dyg,749
|
|
10
|
+
QuickGraphLib/GraphItems/AxVLine.qml,sha256=tPfVFMyCrOxRUGO_oESGydY4XZqWykUoUfnh20SolEI,608
|
|
11
|
+
QuickGraphLib/GraphItems/AxVSpan.qml,sha256=MgJIm_IcK95Z6RcAumW6ron2g_T2I2HiiBiDVBcCCV8,749
|
|
12
|
+
QuickGraphLib/GraphItems/BasicLegend.qml,sha256=4HVmZkOOLtTgpbuVv1XNA7ZpS6LXjVyNPG2p7nM5pz0,660
|
|
13
|
+
QuickGraphLib/GraphItems/BasicLegendItem.qml,sha256=rQHM2hatw4YVf16yo9mL2mugtsD_TluApN-ZQIYXFU0,1311
|
|
14
|
+
QuickGraphLib/GraphItems/Contour.qml,sha256=cSKBLKWlKLNIoFBuAwkZbMIJBO0WvJKG7At5T2PI_Tc,736
|
|
15
|
+
QuickGraphLib/GraphItems/GraphItemDragHandler.qml,sha256=l8QY8LLmXJPbcNGbnilvUVMmCRTAvG_o2POKstKn2d8,1024
|
|
16
|
+
QuickGraphLib/GraphItems/Grid.qml,sha256=wshlBVn8j04VwMoqfVmPWzstmcKuH34WsOExEVB5fYI,1742
|
|
17
|
+
QuickGraphLib/GraphItems/Histogram.qml,sha256=Cdn2aGK2SN6KPDhCVf1M_BLgKwifw-cI6LZIQwu9pkg,1384
|
|
18
|
+
QuickGraphLib/GraphItems/Line.qml,sha256=a0n3XiFB3U3DSZpLpmMZ3mjSHMIEy_tyoTDJE3aAnzY,1714
|
|
19
|
+
QuickGraphLib/GraphItems/Marker.qml,sha256=Spt6dpfGaGJko15MlczL6YeJn4VGhTVD2wHoXjhvPAU,679
|
|
20
|
+
QuickGraphLib/GraphItems/qmldir,sha256=Oei-JPCGE0DDk2AjeciCWp3wJWlp9wFRLzAwyLyGpDo,454
|
|
21
|
+
QuickGraphLib/PreFabs/XYAxes.qml,sha256=L14EwcMDWS_yPqLmHP2z3Jy_Y8mepRVlDCwgIFIewZk,3122
|
|
22
|
+
QuickGraphLib/PreFabs/qmldir,sha256=Xe48hN_BxIgW6eWPncGFMtMA2Bt43ewzZIPrw4I37QM,183
|
|
23
|
+
quickgraphlib_helpers/__init__.py,sha256=p_DRi1Th5mQoPYGtm-QxzEmtTpXTGTdJhkdt9lpK7aM,163
|
|
24
|
+
quickgraphlib_helpers/consts.py,sha256=EZrKEs6HvzBMjkruvdEYnsMXt_XSILmuIcSd0Lzfs-Y,240
|
|
25
|
+
quickgraphlib_helpers/contours.py,sha256=P8MlPPNRtd6L16l2VU2iKHCnni6HJ2AyjkX4f8PAKyA,2380
|
|
26
|
+
quickgraphlib_helpers/export.py,sha256=xFCjg_kpbuQ-uMPrG7Svz0VgVit928HdlSsl59os5e8,6235
|
|
27
|
+
quickgraphlib_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
+
QuickGraphLib-0.1.0a0.dist-info/LICENCE,sha256=9DG9VQDWNuDQKZfh0_q6akoun4YTVRkfeRMExpzQ7kA,1126
|
|
29
|
+
QuickGraphLib-0.1.0a0.dist-info/METADATA,sha256=Q48D0oEIZC1v2hN05ZU1IRwD-VURjMK6AM-8uZqN3Kg,3445
|
|
30
|
+
QuickGraphLib-0.1.0a0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
31
|
+
QuickGraphLib-0.1.0a0.dist-info/top_level.txt,sha256=xau871wpLkl9FHY1B72h6DJXmBpPWDoB63swiG_NmN8,36
|
|
32
|
+
QuickGraphLib-0.1.0a0.dist-info/RECORD,,
|