├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── libraries
│ └── GOPATH__Pipeline_Editor_.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── 2017-01-23 12_04_44-Pipeline Editor.png
├── Pipeline-Editor.iml
├── README.md
├── fmetadata
└── fmets.go
├── genxml
└── genxml.go
├── gfxcanvas
├── gfxcanvas.go
├── grid.go
├── objects.gon
└── util.go
├── gfxinterface
└── interface.go
├── gfxobjects
├── line
│ └── line.go
├── point
│ └── point.go
└── rectangle
│ └── rectangle.go
├── graph
├── graph.go
└── meta.go
├── graphpanel
├── filelist.go
├── graphpanel.go
├── lineedit.go
├── nodelist.go
├── tblargs.go
└── valuelist.go
├── images
├── New folder
│ └── eraser.png
├── circle.png
├── cursor.png
├── eraser.png
├── grid.png
├── hand.png
├── line.png
├── pen.png
├── sizeall.png
├── square.png
├── square.svg
└── type.png
├── janus
└── janus.go
└── main.go
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea*
2 | *.iml
3 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/libraries/GOPATH__Pipeline_Editor_.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | 1.8
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 | 1480698240740
221 |
222 |
223 | 1480698240740
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
--------------------------------------------------------------------------------
/2017-01-23 12_04_44-Pipeline Editor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/2017-01-23 12_04_44-Pipeline Editor.png
--------------------------------------------------------------------------------
/Pipeline-Editor.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/fmetadata/fmets.go:
--------------------------------------------------------------------------------
1 |
2 | package fmets
3 |
4 | //type Flight struct {
5 | // Description string `xml:"Description"`
6 | // Collection_Date string `xml:"Collection_Date"`
7 | // Campaign string `xml:"Campaign"`
8 | // Extraction
9 | // Payload
10 | // Sites_Flown
11 | //}
12 |
13 | //type Extraction struct {
14 | // Software
15 | // Extraction_Date string `xml:"Extraction_Date"`
16 | // Extracted_By string `xml:"Extracted_By"`
17 | // Notes string `xml:"Notes"`
18 | // Disk_Serial_Numbers
19 | //}
20 |
21 | //type Software struct {
22 | // Rev string `xml:"Rev"`
23 | // URL string `xml:"URL"`
24 | // Date string `xml:"Date"`
25 | // LastChangedBy string `xml:"LastChangedBy"`
26 | //}
27 |
28 | //type Disk_Serial_Numbers struct {
29 | // DCC string `xml:"DCC"`
30 | // Camera string `xml:"Camera"`
31 | // GPSIMU string `xml:"GPSIMU"`
32 | // Pony_Express_Backup string `xml:"Pony_Express_Backup"`
33 | //}
34 |
35 | //type Payload struct {
36 | // Spectrometer
37 | // Lidar
38 | // Camera
39 | // GPSIMU
40 | //}
41 |
42 | //type Spectrometer struct {
43 | // Serial_Number string `xml:"Serial_Number"`
44 | // Model string `xml:"Model"`
45 | // Comments string `xml:"Comments"`
46 | // Manufacturer string `xml:"Manufacturer"`
47 | //}
48 |
49 | //type Lidar struct {
50 | // Serial_Number string `xml:"Serial_Number"`
51 | // Model string `xml:"Model"`
52 | // Comments string `xml:"Comments"`
53 | // Manufacturer string `xml:"Manufacturer"`
54 | //}
55 |
56 | //type Camera struct {
57 | // Serial_Number string `xml:"Serial_Number"`
58 | // Model string `xml:"Model"`
59 | // Comments string `xml:"Comments"`
60 | // Manufacturer string `xml:"Manufacturer"`
61 | //}
62 |
63 | //type GPSIMU struct {
64 | // Serial_Number string `xml:"Serial_Number"`
65 | // Model string `xml:"Model"`
66 | // Comments string `xml:"Comments"`
67 | // Manufacturer string `xml:"Manufacturer"`
68 | //}
69 |
70 | //type Sites_Flown struct {
71 | // sites []Site
72 | //}
73 |
74 | //type Site struct {
75 | // SiteID string `xml:"SiteID"`
76 | // DomainName string `xml:"DomainName"`
77 | // Type string `xml:"Type"`
78 | // Northing string `xml:"Northing"`
79 | // Easting string `xml:"Easting"`
80 | // State string `xml:"State"`
81 | // Lat string `xml:"Lat"`
82 | // County string `xml:"County"`
83 | // Long string `xml:"Long"`
84 | // PM_Code string `xml:"PM_Code"`
85 | // Science string `xml:"Science"`
86 | // Domain string `xml:"Domain"`
87 | // Ownership string `xml:"Ownership"`
88 | // Zone string `xml:"Zone"`
89 | //}
90 |
--------------------------------------------------------------------------------
/genxml/genxml.go:
--------------------------------------------------------------------------------
1 | package genxml
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/gfxcanvas"
5 | "github.com/5k3105/Pipeline-Editor/gfxinterface"
6 | "github.com/5k3105/Pipeline-Editor/graphpanel"
7 | "github.com/5k3105/Pipeline-Editor/janus"
8 | "strconv"
9 |
10 | "github.com/beevik/etree"
11 | "github.com/emirpasic/gods/maps/treemap"
12 | )
13 |
14 | const Scalefactor = 10
15 |
16 | var w, h float64 = 30 * Scalefactor, 10 * Scalefactor
17 |
18 | func LoadXML(filename string, canvas *gfxcanvas.Canvas, gp *graphpanel.GraphPanel) { //}*janus.Graph {
19 | canvas.Statusbar.ShowMessage(" start loadxml ", 0)
20 |
21 | gp.SetJanusGraph(canvas.JanusGraph) // update pointer to new janusgraph
22 |
23 | doc := etree.NewDocument()
24 | if err := doc.ReadFromFile(filename); err != nil {
25 | panic(err)
26 | }
27 |
28 | graph := doc.SelectElement("graph")
29 |
30 | // update janusgraph
31 | canvas.JanusGraph.GraphName = graph.SelectElement("graphName").Text()
32 | canvas.JanusGraph.DatasetPath = graph.SelectElement("datasetPath").Text()
33 | canvas.JanusGraph.JobID = graph.SelectElement("jobID").Text()
34 |
35 | // update graphpanel
36 | gp.GraphName.SetText(graph.SelectElement("graphName").Text())
37 | gp.DatasetPath.SetText(graph.SelectElement("datasetPath").Text())
38 | gp.JobID.SetText(graph.SelectElement("jobID").Text())
39 |
40 | nodes := graph.SelectElement("nodes")
41 |
42 | // create all nodes
43 | for _, node := range nodes.SelectElements("node") {
44 |
45 | x, _ := strconv.ParseFloat(node.SelectElement("x").Text(), 64)
46 | y, _ := strconv.ParseFloat(node.SelectElement("y").Text(), 64)
47 | i, _ := strconv.Atoi(node.SelectElement("nodeID").Text())
48 |
49 | canvas.AddRectangleFromFile(i, x, y, w, h,
50 | node.SelectElement("language").Text(),
51 | node.SelectElement("className").Text(),
52 | node.SelectElement("scriptFile").Text())
53 | }
54 |
55 | // create all edges
56 | for _, node := range nodes.SelectElements("node") {
57 |
58 | sid, _ := strconv.Atoi(node.SelectElement("nodeID").Text())
59 | s, _ := canvas.Figures.Get(sid)
60 | source := s.(gfxinterface.Figure)
61 |
62 | edges := node.SelectElement("edges")
63 |
64 | for _, edge := range edges.SelectElements("edge") {
65 | //if edge != struct{} {
66 | tid, _ := strconv.Atoi(edge.Text())
67 | t, _ := canvas.Figures.Get(tid)
68 | target := t.(gfxinterface.Figure)
69 | canvas.AddLineFromFile(source, target)
70 |
71 | }
72 | }
73 |
74 | for _, node := range nodes.SelectElements("node") {
75 |
76 | sid, _ := strconv.Atoi(node.SelectElement("nodeID").Text())
77 | ji, _ := canvas.JanusGraph.Nodes.Get(sid)
78 | jn := ji.(*janus.Node)
79 |
80 | args := node.SelectElement("args")
81 |
82 | for i, arg := range args.ChildElements() {
83 |
84 | if arg.SelectElement("source").Text() == "" {
85 | return
86 | }
87 |
88 | if len(arg.SelectElements("value")) > 1 {
89 | values := treemap.NewWithIntComparator()
90 | for n, ar := range arg.SelectElements("value") {
91 | values.Put(n, ar.Text())
92 | }
93 | jn.Args.Put(i, &janus.Arg{Source: arg.SelectElement("source").Text(),
94 | Values: values})
95 | } else {
96 | jn.Args.Put(i, &janus.Arg{Source: arg.SelectElement("source").Text(),
97 | Value: arg.SelectElement("value").Text(),
98 | Values: treemap.NewWithIntComparator()})
99 | }
100 | }
101 |
102 | // extra element for args table edit-line
103 | jn.Args.Put(len(args.ChildElements()), &janus.Arg{Source: "",
104 | Value: "",
105 | Values: treemap.NewWithIntComparator()})
106 |
107 | }
108 |
109 | canvas.Statusbar.ShowMessage(" end loadxml ", 0)
110 | }
111 |
112 | func GenXML(gp *graphpanel.GraphPanel, jg *janus.Graph, filename string) { // gp to get graphname etc
113 |
114 | doc := etree.NewDocument()
115 | doc.CreateProcInst("xml", `version="1.0" encoding="UTF-8"`)
116 | //doc.CreateProcInst("xml-stylesheet", `type="text/xsl" href="style.xsl"`)
117 |
118 | graph := doc.CreateElement("graph")
119 |
120 | jg.GraphName = gp.GraphName.Text()
121 | jg.DatasetPath = gp.DatasetPath.Text()
122 | jg.JobID = gp.JobID.Text()
123 |
124 | graph.CreateElement("graphName").SetText(jg.GraphName)
125 | graph.CreateElement("datasetPath").SetText(jg.DatasetPath)
126 | graph.CreateElement("jobID").SetText(jg.JobID)
127 |
128 | nodes := graph.CreateElement("nodes")
129 |
130 | for _, x := range jg.Nodes.Values() {
131 | nv := x.(*janus.Node)
132 | node := nodes.CreateElement("node")
133 |
134 | node.CreateElement("nodeID").SetText(nv.NodeID)
135 | node.CreateElement("language").SetText(nv.Language)
136 | node.CreateElement("scriptFile").SetText(nv.ScriptFile)
137 | node.CreateElement("className").SetText(nv.ClassName)
138 |
139 | node.CreateElement("x").SetText(FloatToString(nv.X))
140 | node.CreateElement("y").SetText(FloatToString(nv.Y))
141 |
142 | args := node.CreateElement("args")
143 |
144 | for i, x := range nv.Args.Values() {
145 | av := x.(*janus.Arg)
146 | if av.Source != "" {
147 | arg := args.CreateElement("arg" + strconv.Itoa(i))
148 |
149 | arg.CreateElement("source").SetText(av.Source)
150 | //if av.Value != "" {
151 | arg.CreateElement("value").SetText(av.Value)
152 | //}
153 |
154 | if !av.Values.Empty() {
155 | for _, x := range av.Values.Values() {
156 | xs := x.(string)
157 | arg.CreateElement("value").SetText(xs)
158 | }
159 | }
160 | }
161 | }
162 |
163 | edges := node.CreateElement("edges")
164 |
165 | for _, x := range nv.Edges.Values() {
166 | xv := x.(*janus.Edge)
167 | edges.CreateElement("edge").SetText(xv.String)
168 | }
169 |
170 | antiedges := node.CreateElement("antiEdges")
171 |
172 | for _, x := range nv.AntiEdges.Values() {
173 | xv := x.(*janus.Edge)
174 | antiedges.CreateElement("antiEdge").SetText(xv.String)
175 | }
176 |
177 | }
178 |
179 | doc.Indent(2)
180 | doc.WriteToFile(filename)
181 |
182 | }
183 |
184 | func FloatToString(input_num float64) string {
185 | return strconv.FormatFloat(input_num, 'f', 1, 64)
186 | }
187 |
--------------------------------------------------------------------------------
/gfxcanvas/gfxcanvas.go:
--------------------------------------------------------------------------------
1 | package gfxcanvas
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/gfxinterface"
5 | "github.com/5k3105/Pipeline-Editor/gfxobjects/line"
6 | "github.com/5k3105/Pipeline-Editor/gfxobjects/rectangle"
7 | "github.com/5k3105/Pipeline-Editor/graph"
8 |
9 | "github.com/5k3105/Pipeline-Editor/janus"
10 | "strconv"
11 |
12 | "github.com/emirpasic/gods/maps/treemap"
13 | "github.com/therecipe/qt/core"
14 | "github.com/therecipe/qt/gui"
15 | "github.com/therecipe/qt/widgets"
16 | )
17 |
18 | const Scalefactor = 10
19 | const MvboxSize int = 100
20 |
21 | var ListNodes func() // circular dependencies
22 |
23 | var w, h float64 = 30 * Scalefactor, 10 * Scalefactor
24 |
25 | type Canvas struct {
26 | Scene *widgets.QGraphicsScene
27 | View *widgets.QGraphicsView
28 | Statusbar *widgets.QStatusBar
29 | Graph *graph.Graph
30 | *Grid
31 | Figures *treemap.Map // gfxinterface.Figure
32 | drag bool
33 | drawingline *line.Line
34 | move bool
35 | movingrect *rectangle.Rectangle
36 | JanusGraph *janus.Graph
37 | }
38 |
39 | type Color struct{ R, G, B, A int }
40 |
41 | func NewCanvas(parent *widgets.QMainWindow, lf func()) *Canvas {
42 |
43 | ListNodes = lf
44 |
45 | var canvas = &Canvas{
46 | Scene: widgets.NewQGraphicsScene(parent),
47 | View: widgets.NewQGraphicsView(parent),
48 | Figures: treemap.NewWithIntComparator(),
49 | JanusGraph: janus.NewJanusGraph()}
50 |
51 | canvas.Grid = canvas.NewGrid(0, 100, 100, 64, 32, 5*Scalefactor, 160, 160, 160, 120)
52 |
53 | canvas.Scene.ConnectKeyPressEvent(canvas.keyPressEvent)
54 | canvas.Scene.ConnectMousePressEvent(canvas.mousePressEvent)
55 | canvas.Scene.ConnectWheelEvent(canvas.wheelEvent)
56 | canvas.Scene.ConnectMouseMoveEvent(canvas.mouseMoveEvent)
57 |
58 | canvas.Graph = graph.NewGraph()
59 |
60 | canvas.View.Scale(0.8, 0.8)
61 | canvas.View.Scale(0.8, 0.8)
62 |
63 | point := core.NewQPointF3(300, 300)
64 | canvas.View.CenterOn(point)
65 |
66 | canvas.View.SetViewportUpdateMode(0)
67 |
68 | // canvas.View.Scale(1, -1) // flips image
69 |
70 | return canvas
71 | }
72 | func (c *Canvas) Reset() {
73 | c.Scene.Clear()
74 | c.JanusGraph = janus.NewJanusGraph()
75 | c.Graph = graph.NewGraph()
76 | c.Figures.Clear()
77 | c.Grid = c.NewGrid(0, 100, 100, 64, 32, 5*Scalefactor, 160, 160, 160, 120)
78 | point := core.NewQPointF3(300, 300)
79 | c.View.CenterOn(point)
80 | }
81 |
82 | func (c *Canvas) mouseMoveEvent(e *widgets.QGraphicsSceneMouseEvent) {
83 |
84 | if c.move {
85 | var px, py = e.ScenePos().X(), e.ScenePos().Y()
86 | var x, y = float64((int(px) / 50) * 50), float64((int(py) / 50) * 50) // round to nearest fit
87 |
88 | c.movingrect.SetX(x - w + 50.0) // + float64(MvboxSize))
89 | c.movingrect.SetY(y)
90 | c.movingrect.PrepareGeometryChange()
91 |
92 | }
93 |
94 | if c.drag {
95 | var l = c.drawingline
96 | target := l.Target // Point
97 | target.SetX(e.ScenePos().X())
98 | target.SetY(e.ScenePos().Y())
99 | l.PrepareGeometryChange()
100 |
101 | c.Statusbar.ShowMessage(FloatToString(target.GetX())+" "+FloatToString(target.GetY()), 0)
102 | }
103 |
104 | c.Scene.MouseMoveEventDefault(e)
105 | }
106 |
107 | func (c *Canvas) wheelEvent(e *widgets.QGraphicsSceneWheelEvent) {
108 | if e.Modifiers() == core.Qt__ControlModifier {
109 | if e.Delta() > 0 {
110 | c.View.Scale(1.25, 1.25)
111 | } else {
112 | c.View.Scale(0.8, 0.8)
113 | }
114 | }
115 | }
116 |
117 | func (c *Canvas) mousePressEvent(e *widgets.QGraphicsSceneMouseEvent) {
118 | var px, py = e.ScenePos().X(), e.ScenePos().Y()
119 |
120 | switch e.Button() {
121 | case 1: // left button
122 |
123 | if c.move { // stop moving rectangle
124 | t, _ := c.JanusGraph.Nodes.Get(c.movingrect.GetNode().Id)
125 | tn := t.(*janus.Node)
126 | tn.X = c.movingrect.X
127 | tn.Y = c.movingrect.Y // save to jgraph
128 |
129 | c.movingrect.Over2 = false
130 | c.move = false
131 | c.movingrect = nil
132 | // do not DestroyQGraphicsItem() because this is a pointer to the real rectangle
133 | return
134 | }
135 |
136 | var x, y = float64((int(px) / 50) * 50), float64((int(py) / 50) * 50) // round to nearest fit
137 | //float64((int(px) / 5) * 5)
138 | var m = c.FindRectOverlap(x, y)
139 | if m == nil { // no node
140 |
141 | r := c.AddRectangle(x-w+50, y, w, h)
142 | c.Statusbar.ShowMessage(FloatToString(r.X)+" "+FloatToString(r.Y), 0)
143 |
144 | } else {
145 |
146 | var m = c.FindRectBeneath(px, py)
147 | if m != nil { // found node
148 | if c.drawingline == nil {
149 |
150 | r := m.(*rectangle.Rectangle)
151 | if r.FindRectBeneath(px, py) { // if over move box
152 | r.Over2 = true
153 | c.move = true
154 | c.movingrect = r
155 |
156 | } else {
157 |
158 | c.DrawLine(m, px, py)
159 | c.Statusbar.ShowMessage("drag start", 0)
160 | }
161 | } else {
162 |
163 | c.AddLine(c.drawingline.Source, m)
164 | c.Statusbar.ShowMessage("drag end", 0)
165 |
166 | }
167 | }
168 | }
169 | case 2: // right button
170 |
171 | if c.drag {
172 | c.CancelDraw()
173 | } else {
174 | var m = c.FindRectBeneath(px, py)
175 | if m != nil { // found node
176 | c.RemoveRectangle(m)
177 | }
178 | }
179 |
180 | }
181 |
182 | ListNodes() // callback
183 |
184 | c.Scene.MousePressEventDefault(e)
185 |
186 | }
187 |
188 | func (c *Canvas) RemoveRectangle(t gfxinterface.Figure) {
189 |
190 | var target = t.(*rectangle.Rectangle)
191 | c.RemoveEdges(target)
192 |
193 | if target.Scene().Pointer() != nil {
194 | target.DestroyQGraphicsItem()
195 | c.Figures.Remove(target.GetNode().Id) // remove from treemap
196 |
197 | }
198 |
199 | c.JanusGraph.RemoveNode(target.GetNode().Id)
200 | }
201 |
202 | func (c *Canvas) RemoveEdges(r *rectangle.Rectangle) {
203 |
204 | for _, f := range r.IncomingEdges.Values() { // **
205 | l := f.(*line.Line)
206 | if l.Scene().Pointer() != nil {
207 | l.DestroyQGraphicsPathItem()
208 | }
209 | }
210 |
211 | for _, f := range r.OutgoingEdges.Values() {
212 | l := f.(*line.Line)
213 | if l.Scene().Pointer() != nil {
214 | l.DestroyQGraphicsPathItem()
215 | }
216 | }
217 |
218 | r.IncomingEdges.Clear()
219 | r.OutgoingEdges.Clear() // remove from treemap
220 |
221 | nodeid := strconv.Itoa(r.GetNode().Id)
222 |
223 | // use iterators next
224 |
225 | for _, n := range c.JanusGraph.Nodes.Values() {
226 | for _, ne := range n.(*janus.Node).Edges.Values() {
227 | if ne.(*janus.Edge).String == nodeid {
228 | n.(*janus.Node).Edges.Remove(r.GetNode().Id)
229 | }
230 | }
231 | for _, ne := range n.(*janus.Node).AntiEdges.Values() {
232 | if ne.(*janus.Edge).String == nodeid {
233 | n.(*janus.Node).AntiEdges.Remove(r.GetNode().Id)
234 | }
235 | }
236 | }
237 |
238 | }
239 |
240 | func (c *Canvas) AddRectangle(x, y, w, h float64) *rectangle.Rectangle {
241 |
242 | i, r := rectangle.NewRectangle(x, y, w, h, c.Graph)
243 | c.Figures.Put(i, r)
244 | c.Scene.AddItem(r)
245 |
246 | c.JanusGraph.AddNode(i, x, y)
247 |
248 | return r
249 | }
250 |
251 | func (c *Canvas) AddRectangleFromFile(i int, x, y, w, h float64, language, classname, scriptfile string) *rectangle.Rectangle {
252 |
253 | i, r := rectangle.NewRectangleFromFile(i, x, y, w, h, c.Graph)
254 | c.Figures.Put(i, r)
255 | c.Scene.AddItem(r)
256 |
257 | c.JanusGraph.AddNodeFromFile(i, x, y, language, classname, scriptfile)
258 |
259 | return r
260 | }
261 |
262 | func (c *Canvas) AddLine(source gfxinterface.Figure, target gfxinterface.Figure) {
263 |
264 | l := line.AddLine(c.Graph, source, target)
265 |
266 | l.Source.AddEdgeOutgoing(l)
267 | l.Target.AddEdgeIncoming(l)
268 |
269 | c.Scene.AddItem(l)
270 |
271 | if c.drawingline.Scene().Pointer() != nil {
272 | c.drawingline.DestroyQGraphicsPathItem()
273 | c.drawingline = nil
274 | c.drag = false
275 |
276 | }
277 |
278 | t, _ := c.JanusGraph.Nodes.Get(target.GetNode().Id)
279 | tn := t.(*janus.Node)
280 |
281 | tn.AddEdge(source.GetNode().Id, "Outgoing Edge")
282 |
283 | s, _ := c.JanusGraph.Nodes.Get(source.GetNode().Id)
284 | sn := s.(*janus.Node)
285 |
286 | sn.AddEdge(target.GetNode().Id, "Incoming Edge")
287 |
288 | }
289 |
290 | func (c *Canvas) AddLineFromFile(source gfxinterface.Figure, target gfxinterface.Figure) {
291 |
292 | t, _ := c.JanusGraph.Nodes.Get(target.GetNode().Id)
293 | tn := t.(*janus.Node)
294 |
295 | tn.AddEdge(source.GetNode().Id, "Outgoing Edge")
296 |
297 | // s -> t
298 | s, _ := c.JanusGraph.Nodes.Get(source.GetNode().Id)
299 | sn := s.(*janus.Node)
300 |
301 | sn.AddEdge(target.GetNode().Id, "Incoming Edge")
302 |
303 | l := line.AddLine(c.Graph, source, target)
304 |
305 | c.Scene.AddItem(l)
306 |
307 | l.Source.AddEdgeOutgoing(l)
308 | l.Target.AddEdgeIncoming(l)
309 |
310 | }
311 |
312 | func (c *Canvas) DrawLine(source gfxinterface.Figure, tx, ty float64) {
313 | l := line.DrawLine(source, tx, ty)
314 | c.Scene.AddItem(l)
315 | c.drawingline = l
316 | c.drag = true
317 | }
318 |
319 | func (c *Canvas) keyPressEvent(e *gui.QKeyEvent) {
320 |
321 | if e.Modifiers() == core.Qt__ControlModifier {
322 | switch int32(e.Key()) {
323 | case int32(core.Qt__Key_Equal):
324 | c.View.Scale(1.25, 1.25)
325 |
326 | case int32(core.Qt__Key_Minus):
327 | c.View.Scale(0.8, 0.8)
328 | }
329 | }
330 |
331 | if e.Key() == int(core.Qt__Key_Escape) {
332 | if c.drag {
333 | c.CancelDraw()
334 | }
335 | }
336 | }
337 |
338 | func (c *Canvas) CancelDraw() {
339 | if c.drawingline.Scene().Pointer() != nil {
340 | c.drawingline.DestroyQGraphicsPathItem()
341 | c.drawingline = nil
342 | c.drag = false
343 |
344 | }
345 | }
346 |
347 | func (c *Canvas) ClearScene() {
348 | c.Scene.Clear()
349 | c.View.SetScene(c.Scene)
350 | c.View.Show()
351 |
352 | }
353 |
354 | func (c *Canvas) ShowPic(filepath, filetype string) {
355 |
356 | // string from core.QByteArray like this: (*QByteArray).ConstData()
357 |
358 | ft := core.NewQByteArray2(filetype,len(filetype))
359 |
360 | ir := gui.NewQImageReader3(filepath, ft)
361 | img := ir.Read()
362 |
363 | pix := gui.QPixmap_FromImage(img, 0)
364 |
365 | c.Scene.Clear()
366 | c.Scene.AddPixmap(pix)
367 |
368 | c.View.SetScene(c.Scene)
369 | c.View.Show()
370 |
371 | }
372 |
373 | func FloatToString(input_num float64) string {
374 | return strconv.FormatFloat(input_num, 'f', 1, 64)
375 | }
376 |
--------------------------------------------------------------------------------
/gfxcanvas/grid.go:
--------------------------------------------------------------------------------
1 | package gfxcanvas
2 |
3 | import "github.com/therecipe/qt/gui"
4 |
5 | type Grid struct {
6 | Color
7 | PenWidth int
8 | X, Y float64
9 | Vstep, Hstep, Step float64
10 | }
11 |
12 | func (c *Canvas) NewGrid(penwidth int, x, y, vstep, hstep, step float64, r, g, b, a int) *Grid {
13 |
14 | var inpcolor = Color{r, g, b, a}
15 |
16 | var grid = &Grid{
17 | Color: inpcolor,
18 | PenWidth: penwidth,
19 | X: x,
20 | Y: y,
21 | Vstep: vstep,
22 | Hstep: hstep,
23 | Step: step}
24 |
25 | var color = gui.NewQColor3(r, g, b, a)
26 | var pen = gui.NewQPen3(color)
27 | pen.SetWidth(penwidth)
28 |
29 | for x := grid.X; x <= hstep*step; x += step {
30 | c.Scene.AddLine2(x, 0, x, vstep*step, pen)
31 | }
32 |
33 | for y := grid.Y; y <= vstep*step; y += step {
34 | c.Scene.AddLine2(0, y, hstep*step, y, pen)
35 | }
36 |
37 | c.View.SetScene(c.Scene)
38 | c.View.Show()
39 | return grid
40 | }
41 |
42 | // vstep := 24.0
43 | // hstep := 64.0
44 | // step := 5.0
45 |
--------------------------------------------------------------------------------
/gfxcanvas/objects.gon:
--------------------------------------------------------------------------------
1 | package RoundedRect
2 |
3 | import (
4 | "github.com/therecipe/qt/core"
5 | "github.com/therecipe/qt/gui"
6 | "github.com/therecipe/qt/widgets"
7 | )
8 |
9 | type RoundedRect struct {
10 | *widgets.QGraphicsItem
11 | Scene *widgets.QGraphicsScene
12 | X, Y float64
13 | W, H int
14 | }
15 |
16 | func NewRectangle(x, y float64, step, w, h int, s *widgets.QGraphicsScene) *RoundedRect {
17 | i := &RoundedRect{}
18 | i.QGraphicsItem = widgets.NewQGrapicsItem(nil)
19 | i.Scene = s
20 | i.X = x
21 | i.Y = y
22 | i.W = w
23 | i.H = h
24 |
25 | i.SetAcceptHoverEvents(true)
26 | i.ConnectHoverEnterEvent(i.rectHoverEnterEvent)
27 | i.ConnectHoverLeaveEvent(i.rectHoverLeaveEvent)
28 |
29 | i.ConnectBoundingRect(boundingRect)
30 | i.ConnectPaint(paint)
31 |
32 | return i
33 | }
34 |
35 | func (i *widgets.QGraphicsItem) paint(p *gui.QPainter, o *QStyleOptionGraphicsItem, w *QWidget) {
36 | var color = gui.NewQColor2(0, 0, 0, 255) // r,g,b,a
37 | var pen = gui.NewQPen3(color)
38 | pen.SetWidth(1)
39 | var brush = gui.NewQBrush()
40 |
41 | var x, y = float64((int(i.X) / step) * step), float64((int(i.Y) / step) * step) // round to nearest fit
42 |
43 | p.SetRenderHint(1) // Antiailiasing
44 | var path = gui.NewQPainterPath()
45 | path.AddRoundedRect2(x, y, i.W, i.H, 10, 10)
46 | p.SetPen(pen)
47 | color = gui.NewQColor2(0, 0, 0, 100) // r,g,b,a
48 | p.FillPath(path, color)
49 | p.DrawPath(path)
50 | }
51 |
52 | func (i *widgets.QGraphicsItem) boundingRect() *core.QRectF {
53 | return core.QRectF(150, 150, 60, 60)
54 | }
55 |
56 | func (i *widgets.QGraphicsItem) rectHoverEnterEvent(e *widgets.QGraphicsSceneHoverEvent) {
57 | var x, y = e.Pos().X(), e.Pos().Y()
58 | var i = c.Scene.ItemAt3(x, y, nil)
59 | var p = core.NewQPointF()
60 | p = i.ScenePos()
61 | x, y = p.X(), p.Y()
62 | //c.Statusbar.ShowMessage("object is: "+i.Data(0).ToString(), 0)
63 | c.Statusbar.ShowMessage("object is: "+FloatToString(x)+" "+FloatToString(y), 0)
64 |
65 | var color = gui.NewQColor2(0, 0, 0, 255/2) // r,g,b,a
66 | var pen = gui.NewQPen3(color)
67 | pen.SetWidth(0)
68 | var brush = gui.NewQBrush()
69 | r := widgets.NewQGraphicsRectItem3(x+(20/2), y+(10/2), 20/2, 10/2, nil)
70 | r.SetPen(pen)
71 | r.SetBrush(brush)
72 | c.Scene.AddItem(r)
73 |
74 | //c.Statusbar.ShowMessage("hovering: "+FloatToString(e.Pos().X())+", "+FloatToString(e.Pos().Y()), 0)
75 | }
76 |
77 | func (i *widgets.QGraphicsItem) rectHoverLeaveEvent(e *widgets.QGraphicsSceneHoverEvent) {
78 | var x, y = e.Pos().X(), e.Pos().Y()
79 | var i = c.Scene.ItemAt3(x, y, nil)
80 | c.Scene.RemoveItem(i)
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/gfxcanvas/util.go:
--------------------------------------------------------------------------------
1 | package gfxcanvas
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/gfxinterface"
5 | "github.com/5k3105/Pipeline-Editor/gfxobjects/rectangle"
6 | )
7 |
8 | func (c *Canvas) FindRectOverlap(x, y float64) gfxinterface.Figure {
9 | // overlap of 2 rectangles
10 |
11 | // detect right and below
12 | // L2x, L2y := x, y
13 | // R2x, R2y := x+300, y+100
14 |
15 | // detect left and below
16 | L2x, L2y := x-300+50, y
17 | R2x, R2y := x, y+100
18 |
19 | for _, f := range c.Figures.Values() {
20 | i := f.(*rectangle.Rectangle)
21 |
22 | L1x, L1y := i.X, i.Y
23 | R1x, R1y := i.X+i.W, i.Y+i.H
24 |
25 | if L2x < R1x && R2x > L1x && L2y < R1y && R2y > L1y {
26 | return i
27 | }
28 | }
29 |
30 | return nil
31 | }
32 |
33 | func (c *Canvas) FindRectBeneath(x, y float64) gfxinterface.Figure {
34 | // point within another rect area
35 | for _, f := range c.Figures.Values() {
36 | i := f.(*rectangle.Rectangle)
37 |
38 | if x >= i.X && x <= i.X+i.W && y >= i.Y && y <= i.Y+i.H {
39 | return i
40 | }
41 | }
42 |
43 | return nil
44 | }
45 |
46 | //func (c *Canvas) FindRectBeneath2(x, y, iX, iY float64) bool {
47 |
48 | // if x >= iX+15 && x <= iX+20 && y >= iY && y <= iY+5 {
49 | // return true
50 | // } else {
51 | // return false
52 | // }
53 |
54 | //}
55 |
--------------------------------------------------------------------------------
/gfxinterface/interface.go:
--------------------------------------------------------------------------------
1 | package gfxinterface
2 |
3 | import "github.com/5k3105/Pipeline-Editor/graph"
4 |
5 | type Figure interface {
6 | GetX() float64
7 | SetX(x float64)
8 | GetY() float64
9 | SetY(y float64)
10 | GetW() float64
11 | GetNode() *graph.Node
12 | AddEdgeIncoming(l Link)
13 | AddEdgeOutgoing(l Link)
14 | // RemoveEdge()
15 | }
16 |
17 | type Link interface {
18 | GetEdge() *graph.Edge
19 | }
20 |
--------------------------------------------------------------------------------
/gfxobjects/line/line.go:
--------------------------------------------------------------------------------
1 | package line
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/gfxinterface"
5 | "github.com/5k3105/Pipeline-Editor/gfxobjects/point"
6 | "github.com/5k3105/Pipeline-Editor/graph"
7 |
8 | "github.com/therecipe/qt/core"
9 | "github.com/therecipe/qt/gui"
10 | "github.com/therecipe/qt/widgets"
11 | )
12 |
13 | const penwidth int = 5
14 |
15 | type Line struct {
16 | *widgets.QGraphicsPathItem
17 | Edge *graph.Edge // ?
18 | Type string
19 | Source gfxinterface.Figure
20 | Target gfxinterface.Figure
21 | SX, SY float64 // source
22 | TX, TY float64 // target
23 | fgcolor Color
24 | over bool
25 | }
26 |
27 | type Color struct{ R, G, B, A int }
28 |
29 | func AddLine(g *graph.Graph, source gfxinterface.Figure, target gfxinterface.Figure) *Line {
30 |
31 | var s, t = source.GetNode(), target.GetNode()
32 |
33 | var l = &Line{
34 | QGraphicsPathItem: widgets.NewQGraphicsPathItem(nil),
35 | Type: "Line",
36 | Edge: g.AddEdge(s, t),
37 | Source: source,
38 | Target: target,
39 | SX: source.GetX(),
40 | SY: source.GetY(),
41 | TX: target.GetX(),
42 | TY: target.GetY()}
43 |
44 | l.ConnectBoundingRect(l.boundingRect)
45 | l.ConnectPaint(l.paint)
46 |
47 | return l
48 | }
49 |
50 | //func AddLineFromFile(g *graph.Graph, source gfxinterface.Figure, target gfxinterface.Figure) *Line {
51 |
52 | // var s, t = source.GetNode(), target.GetNode()
53 |
54 | // var l = &Line{
55 | // QGraphicsPathItem: widgets.NewQGraphicsPathItem(nil),
56 | // Type: "Line",
57 | // Edge: g.AddEdge(s, t),
58 | // Source: source,
59 | // Target: target,
60 | // SX: source.GetX(),
61 | // SY: source.GetY(),
62 | // TX: target.GetX(),
63 | // TY: target.GetY()}
64 |
65 | // l.ConnectBoundingRect(l.boundingRect)
66 | // l.ConnectPaint(l.paint)
67 |
68 | // return l
69 | //}
70 |
71 | func (l *Line) GetEdge() *graph.Edge { return l.Edge }
72 |
73 | func (l *Line) paint(p *gui.QPainter, o *widgets.QStyleOptionGraphicsItem, widget *widgets.QWidget) {
74 | var color = gui.NewQColor3(0, 0, 0, 255)
75 | var brush = gui.NewQBrush3(color, 0) // solid = 1, nobrush = 0
76 | var pen = gui.NewQPen3(color)
77 | pen.SetWidth(penwidth)
78 |
79 | p.SetRenderHint(1, true) // Antiailiasing
80 | p.SetPen(pen)
81 | p.SetBrush(brush)
82 |
83 | path := gui.NewQPainterPath()
84 |
85 | source := l.Source
86 | target := l.Target
87 |
88 | var sx, sy, tx, ty, w = source.GetX(), source.GetY(), target.GetX(), target.GetY(), target.GetW()
89 | sx, sy = sx+(w/2.0), sy+100.0 // bottom center is output node
90 | tx, ty = tx+(w/2.0), ty // top center is input node
91 | path.MoveTo2(sx, sy)
92 | sy = sy + 50.0 // offset by single step
93 | path.LineTo2(sx, sy)
94 |
95 | //var A, B, C int
96 |
97 | // target straight down
98 | if sy < ty && sx == tx {
99 | path.LineTo2(tx, ty)
100 | p.DrawPath(path)
101 | drawArrow(p, tx, ty)
102 | return
103 | }
104 |
105 | // target straight up
106 | if sy > ty && sx == tx {
107 | var offset = (w/2 + 50.0)
108 | sx = sx + offset
109 | path.LineTo2(sx, sy) // A
110 | ty = ty - 50.0
111 | path.LineTo2(sx, ty) // B
112 | path.LineTo2(tx, ty) // C
113 |
114 | ty = ty + 50.0
115 | path.LineTo2(tx, ty)
116 | p.DrawPath(path)
117 | drawArrow(p, tx, ty)
118 | return
119 | }
120 |
121 | // target bottom left
122 | if sx > tx && sy < ty {
123 | path.LineTo2(tx, sy)
124 | path.LineTo2(tx, ty)
125 | p.DrawPath(path)
126 | drawArrow(p, tx, ty)
127 | return
128 | }
129 |
130 | // target bottom right
131 | if sx < tx && sy < ty {
132 | path.LineTo2(tx, sy)
133 | path.LineTo2(tx, ty)
134 | p.DrawPath(path)
135 | drawArrow(p, tx, ty)
136 | return
137 | }
138 |
139 | // target top right
140 | if sx < tx && sy > ty {
141 | var offset = (w/2 + 50.0)
142 | if sx+offset <= tx-offset { // between
143 | sx = sx + offset
144 | path.LineTo2(sx, sy) // A
145 |
146 | ty = ty - 50.0
147 | path.LineTo2(sx, ty) // B
148 | path.LineTo2(tx, ty) // C
149 |
150 | ty = ty + 50.0
151 | path.LineTo2(tx, ty)
152 | p.DrawPath(path)
153 | drawArrow(p, tx, ty)
154 | return
155 | } else { // around
156 | tx = tx + offset
157 | path.LineTo2(tx, sy) // A
158 |
159 | ty = ty - 50.0
160 | path.LineTo2(tx, ty) // B
161 | tx = tx - offset
162 | path.LineTo2(tx, ty) // C
163 |
164 | ty = ty + 50.0
165 | path.LineTo2(tx, ty)
166 | p.DrawPath(path)
167 | drawArrow(p, tx, ty)
168 | return
169 | }
170 | }
171 |
172 | // target top left
173 | if sx > tx && sy > ty {
174 | var offset = (w/2 + 50.0)
175 | if sx-offset >= tx+offset { // between
176 | sx = sx - offset
177 | path.LineTo2(sx, sy) // A
178 |
179 | ty = ty - 50.0
180 | path.LineTo2(sx, ty) // B
181 | path.LineTo2(tx, ty) // C
182 |
183 | ty = ty + 50.0
184 | path.LineTo2(tx, ty)
185 | p.DrawPath(path)
186 | drawArrow(p, tx, ty)
187 | return
188 | } else { // around
189 | tx = tx - offset
190 | path.LineTo2(tx, sy) // A
191 |
192 | ty = ty - 50.0
193 | path.LineTo2(tx, ty) // B
194 | tx = tx + offset
195 | path.LineTo2(tx, ty) // C
196 |
197 | ty = ty + 50.0
198 | path.LineTo2(tx, ty)
199 | p.DrawPath(path)
200 | drawArrow(p, tx, ty)
201 | return
202 | }
203 | }
204 |
205 | }
206 |
207 | func drawArrow(p *gui.QPainter, x, y float64) {
208 | var color = gui.NewQColor3(0, 0, 0, 255)
209 | var brush = gui.NewQBrush3(color, 1) // solid = 1, nobrush = 0
210 | var pen = gui.NewQPen3(color)
211 | pen.SetWidth(0)
212 |
213 | p.SetRenderHint(1, true) // Antiailiasing
214 | p.SetPen(pen)
215 | p.SetBrush(brush)
216 |
217 | path := gui.NewQPainterPath()
218 |
219 | path.MoveTo2(x-10, y-20)
220 | path.LineTo2(x+10, y-20)
221 | path.LineTo2(x, y)
222 | path.LineTo2(x-10, y-20)
223 |
224 | p.DrawPath(path)
225 | }
226 |
227 | func (l *Line) boundingRect() *core.QRectF {
228 | source := l.Source
229 | target := l.Target
230 | return core.NewQRectF4(source.GetX(), source.GetY(), target.GetX(), target.GetY())
231 | }
232 |
233 | func (l *Line) boundingRectDL() *core.QRectF {
234 | source := l.Source // Rectangle
235 | target := l.Target // Point
236 | return core.NewQRectF4(source.GetX(), source.GetY(), target.GetX(), target.GetY())
237 | }
238 |
239 | // draw temporary line
240 | func DrawLine(source gfxinterface.Figure, tx, ty float64) *Line {
241 |
242 | var target = &point.Point{X: tx, Y: ty}
243 |
244 | l := &Line{
245 | QGraphicsPathItem: widgets.NewQGraphicsPathItem(nil),
246 | Type: "Line",
247 | Source: source,
248 | Target: target}
249 |
250 | l.ConnectBoundingRect(l.boundingRectDL)
251 | l.ConnectPaint(l.draw)
252 |
253 | return l
254 | }
255 |
256 | func (l *Line) draw(p *gui.QPainter, o *widgets.QStyleOptionGraphicsItem, widget *widgets.QWidget) {
257 | var color = gui.NewQColor3(0, 0, 0, 255)
258 | var brush = gui.NewQBrush3(color, 0)
259 | var pen = gui.NewQPen3(color)
260 | pen.SetWidth(penwidth)
261 |
262 | p.SetRenderHint(1, true) // Antiailiasing
263 | p.SetPen(pen)
264 | p.SetBrush(brush)
265 |
266 | path := gui.NewQPainterPath()
267 | // center line start, extend to current cursor location
268 | source := l.Source // Rectangle
269 | target := l.Target // Point
270 | path.MoveTo2(source.GetX()+source.GetW()/2, source.GetY()+100/2) // GetH() ??
271 | path.LineTo2(target.GetX(), target.GetY())
272 |
273 | p.DrawPath(path)
274 | }
275 |
276 | //func AutoNumber() int64 {
277 | // autonumber += 1
278 | // return autonumber
279 | //}
280 |
281 | //------------------------------------------------------------------------------
282 |
283 | //type Line struct {
284 | // *widgets.QGraphicsPathItem
285 | // Color
286 | // Id int
287 | // Source Shape
288 | // Target Shape
289 | // // SId, TId int
290 | // // SX, SY float64 // source
291 | // // TX, TY float64 // target
292 | // over bool
293 | //}
294 |
295 | // SX: sx,
296 | // SY: sy,
297 | // TX: tx,
298 | // TY: ty}
299 |
300 | // paint:
301 | // l.SetPath(path)
302 | // l.Scene.AddPath(path, pen, brush)
303 |
--------------------------------------------------------------------------------
/gfxobjects/point/point.go:
--------------------------------------------------------------------------------
1 | package point
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/gfxinterface"
5 | "github.com/5k3105/Pipeline-Editor/graph"
6 | )
7 |
8 | type Point struct {
9 | X, Y float64
10 | }
11 |
12 | func (p *Point) GetX() float64 { return p.X }
13 | func (p *Point) SetX(x float64) { p.X = x }
14 | func (p *Point) GetY() float64 { return p.Y }
15 | func (p *Point) SetY(y float64) { p.Y = y }
16 | func (p *Point) GetW() float64 { return 0.0 }
17 | func (p *Point) GetNode() *graph.Node { return nil }
18 |
19 | func (p *Point) AddEdgeIncoming(edge gfxinterface.Link) {}
20 |
21 | func (p *Point) AddEdgeOutgoing(edge gfxinterface.Link) {}
22 |
--------------------------------------------------------------------------------
/gfxobjects/rectangle/rectangle.go:
--------------------------------------------------------------------------------
1 | package rectangle
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/gfxinterface"
5 | "github.com/5k3105/Pipeline-Editor/graph"
6 | "strconv"
7 |
8 | "github.com/emirpasic/gods/maps/treemap"
9 | "github.com/therecipe/qt/core"
10 | "github.com/therecipe/qt/gui"
11 | "github.com/therecipe/qt/widgets"
12 | )
13 |
14 | const MvboxSize float64 = 100
15 | const penwidth int = 5
16 |
17 | type Rectangle struct {
18 | *widgets.QGraphicsItem
19 | Type string
20 | Name string
21 | Node *graph.Node
22 | IncomingEdges *treemap.Map //[]gfxinterface.Link
23 | OutgoingEdges *treemap.Map //[]gfxinterface.Link
24 | X, Y float64
25 | W, H float64
26 | over bool
27 | Over2 bool
28 | fgcolor Color
29 | bgcolor Color
30 | }
31 |
32 | type Color struct{ R, G, B, A int }
33 |
34 | func (r *Rectangle) GetX() float64 { return r.X }
35 | func (r *Rectangle) SetX(x float64) { r.X = x }
36 | func (r *Rectangle) GetY() float64 { return r.Y }
37 | func (r *Rectangle) SetY(y float64) { r.Y = y }
38 | func (r *Rectangle) GetW() float64 { return r.W }
39 | func (r *Rectangle) GetNode() *graph.Node { return r.Node }
40 |
41 | func (r *Rectangle) AddEdgeIncoming(l gfxinterface.Link) {
42 | e := l.GetEdge()
43 | r.IncomingEdges.Put(e.Id, l)
44 | }
45 |
46 | func (r *Rectangle) AddEdgeOutgoing(l gfxinterface.Link) {
47 | e := l.GetEdge()
48 | r.OutgoingEdges.Put(e.Id, l)
49 | }
50 |
51 | func NewRectangle(x, y, w, h float64, g *graph.Graph) (int, *Rectangle) {
52 |
53 | r := &Rectangle{
54 | QGraphicsItem: widgets.NewQGraphicsItem(nil),
55 | Type: "Rectangle",
56 | Node: g.AddNode(),
57 | IncomingEdges: treemap.NewWithIntComparator(),
58 | OutgoingEdges: treemap.NewWithIntComparator(),
59 | X: x,
60 | Y: y,
61 | W: w,
62 | H: h,
63 | fgcolor: Color{0, 0, 0, 255},
64 | bgcolor: Color{0, 0, 0, 100},
65 | }
66 |
67 | r.SetAcceptHoverEvents(true)
68 | r.ConnectHoverEnterEvent(r.hoverEnterEvent)
69 | r.ConnectHoverLeaveEvent(r.hoverLeaveEvent)
70 |
71 | r.ConnectBoundingRect(r.boundingRect)
72 | r.ConnectPaint(r.paint)
73 |
74 | return r.Node.Id, r
75 | }
76 |
77 | func NewRectangleFromFile(i int, x, y, w, h float64, g *graph.Graph) (int, *Rectangle) {
78 |
79 | r := &Rectangle{
80 | QGraphicsItem: widgets.NewQGraphicsItem(nil),
81 | Type: "Rectangle",
82 | Node: g.AddNodeFromFile(i),
83 | IncomingEdges: treemap.NewWithIntComparator(),
84 | OutgoingEdges: treemap.NewWithIntComparator(),
85 | X: x,
86 | Y: y,
87 | W: w,
88 | H: h,
89 | fgcolor: Color{0, 0, 0, 255},
90 | bgcolor: Color{0, 0, 0, 100},
91 | }
92 |
93 | r.SetAcceptHoverEvents(true)
94 | r.ConnectHoverEnterEvent(r.hoverEnterEvent)
95 | r.ConnectHoverLeaveEvent(r.hoverLeaveEvent)
96 |
97 | r.ConnectBoundingRect(r.boundingRect)
98 | r.ConnectPaint(r.paint)
99 |
100 | return r.Node.Id, r
101 | }
102 |
103 | func (r *Rectangle) paint(p *gui.QPainter, o *widgets.QStyleOptionGraphicsItem, w *widgets.QWidget) {
104 |
105 | var color = gui.NewQColor3(r.fgcolor.R, r.fgcolor.G, r.fgcolor.B, r.fgcolor.A) // r,g,b,a
106 |
107 | var pen = gui.NewQPen3(color)
108 | pen.SetWidth(penwidth)
109 |
110 | if r.Over2 {
111 | pen.SetStyle(0)
112 | }
113 |
114 | p.SetRenderHint(1, true) // Antiailiasing
115 | var path = gui.NewQPainterPath()
116 | path.AddRoundedRect2(r.X, r.Y, r.W, r.H, 1, 1, 0) // Qt::AbsoluteSize
117 | p.SetPen(pen)
118 | p.DrawPath(path)
119 |
120 | if r.over {
121 | color = gui.NewQColor3(r.bgcolor.R, r.bgcolor.G, r.bgcolor.B, r.bgcolor.A) // r,g,b,a
122 | var brush = gui.NewQBrush3(color, 1)
123 | p.FillPath(path, brush)
124 |
125 | color = gui.NewQColor3(0, 0, 0, 60) // r,g,b,a
126 | var pen2 = gui.NewQPen2(0) // no pen
127 |
128 | var brush2 = gui.NewQBrush3(color, 1)
129 | var path2 = gui.NewQPainterPath()
130 |
131 | p.SetPen(pen2)
132 | path2.AddRoundedRect2(r.X+r.W-MvboxSize, r.Y, MvboxSize, MvboxSize, 1, 1, 0) // moveme box // (r.X+r.W-5, r.Y, 5, 5, 1, 1, 0)
133 | p.FillPath(path2, brush2)
134 | p.DrawPath(path2)
135 | }
136 |
137 | // if selected {}
138 |
139 | var font = gui.NewQFont2("verdana", 20, 1, false)
140 | p.SetFont(font)
141 |
142 | var qpf = core.NewQPointF3(r.X+10.0, r.Y+r.H-10.0)
143 |
144 | if r.Name == "" {
145 | p.DrawText(qpf, "Node "+strconv.Itoa(r.Node.Id))
146 | } else {
147 | p.DrawText(qpf, r.Name) //+" "+strconv.Itoa(r.Node.Id))
148 | }
149 | //p.DrawPath(path)
150 | }
151 |
152 | func (r *Rectangle) boundingRect() *core.QRectF {
153 | return core.NewQRectF4(r.X, r.Y, r.W, r.H)
154 | }
155 |
156 | func (r *Rectangle) hoverEnterEvent(e *widgets.QGraphicsSceneHoverEvent) {
157 | r.over = true
158 | r.Update(core.NewQRectF4(r.X, r.Y, r.W, r.H))
159 | }
160 |
161 | func (r *Rectangle) hoverLeaveEvent(e *widgets.QGraphicsSceneHoverEvent) {
162 | r.over = false
163 | r.Update(core.NewQRectF4(r.X, r.Y, r.W, r.H))
164 | }
165 |
166 | func (r *Rectangle) FindRectBeneath(x, y float64) bool {
167 | var iX, iY, iW = r.X, r.Y, r.W
168 | //if x >= iX+iW-5 && x <= iX+iW && y >= iY && y <= iY+5 {
169 | if x >= iX+iW-MvboxSize && x <= iX+iW && y >= iY && y <= iY+MvboxSize {
170 | return true
171 | } else {
172 | return false
173 | }
174 |
175 | }
176 |
177 | func FloatToString(input_num float64) string {
178 | return strconv.FormatFloat(input_num, 'f', 6, 64)
179 | }
180 |
--------------------------------------------------------------------------------
/graph/graph.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import (
4 | "encoding/json"
5 | "os"
6 | )
7 |
8 | var autonumber int
9 |
10 | type Graph struct {
11 | Id int
12 | Nodes []*Node `json:",omitempty"`
13 | }
14 |
15 | type Node struct {
16 | Id int
17 | IncomingEdges []*Edge
18 | OutgoingEdges []*Edge
19 | }
20 |
21 | type Edge struct {
22 | Id int
23 | Source *Node `json:",omitempty"`
24 | Target *Node `json:",omitempty"`
25 | }
26 |
27 | func NewGraph() *Graph {
28 | var g Graph
29 | g.Id = AutoNumber()
30 | return &g
31 | }
32 |
33 | // Encode to file
34 | func Save(path string, g *Graph) error {
35 | file, err := os.Create(path)
36 | if err == nil {
37 | encoder := json.NewEncoder(file)
38 | encoder.Encode(g)
39 | }
40 | file.Close()
41 | return err
42 | }
43 |
44 | // Decode file
45 | func Load(path string, g *Graph) (error, *Graph) {
46 | file, err := os.Open(path)
47 | if err == nil {
48 | decoder := json.NewDecoder(file)
49 | err = decoder.Decode(g)
50 | }
51 | file.Close()
52 | return err, g
53 | }
54 |
55 | func (g *Graph) AddNode() *Node {
56 | var n Node
57 |
58 | n.Id = AutoNumber()
59 | g.Nodes = append(g.Nodes, &n)
60 |
61 | return &n
62 | }
63 |
64 | func (g *Graph) AddNodeFromFile(i int) *Node {
65 | var n Node
66 |
67 | n.Id = i //AutoNumber()
68 | autonumber = i // hack
69 | g.Nodes = append(g.Nodes, &n)
70 |
71 | return &n
72 | }
73 |
74 | func (g *Graph) AddEdge(source, target *Node) *Edge {
75 | var e Edge
76 |
77 | e.Id = AutoNumber()
78 | e.Source = source
79 | e.Target = target
80 |
81 | s, er := g.NodeFind(source.Id)
82 | Check(er)
83 |
84 | t, er := g.NodeFind(source.Id)
85 | Check(er)
86 |
87 | g.Nodes[s].OutgoingEdges = append(g.Nodes[s].OutgoingEdges, &e)
88 | g.Nodes[t].IncomingEdges = append(g.Nodes[t].IncomingEdges, &e)
89 |
90 | return &e
91 | }
92 |
93 | func (g *Graph) NodeFind(Id int) (i int, err error) {
94 | var s = g.Nodes
95 |
96 | for i, v := range s {
97 | if v.Id == Id {
98 | return i, err
99 | }
100 | }
101 | return 0, err
102 | }
103 |
104 | func AutoNumber() int {
105 | autonumber += 1
106 | return autonumber
107 | }
108 |
109 | func Check(e error) {
110 | if e != nil {
111 | //_, file, line, _ := runtime.Caller(1)
112 | //fmt.Println(line, "\t", file, "\n", e)
113 | //os.Exit(1)
114 | }
115 | }
116 |
117 | //func AutoNumber() Id {
118 | // var i Id
119 | // autonumber += 1
120 | // i = autonumber
121 | // return i
122 | //}
123 |
124 | //func (g *Graph) RemoveNode(n Node) []Node {
125 | // var s = g.Nodes
126 |
127 | // for i, v := range s {
128 | // if v == n {
129 | // g.Nodes = append(s[0:i], s[i+1:]...)
130 | // return g.Nodes
131 | // }
132 | // }
133 | // return s
134 |
135 | //}
136 |
137 | //func (g *Graph) RemoveEdge() {
138 |
139 | //}
140 |
141 | //------------------------------------------------------------------------------
142 |
143 | //type Node struct {
144 | // Id
145 | // //X, Y float64 `json:",omitempty"`
146 | // //Incoming []Edge `json:",omitempty"`
147 | // //Outgoing []Edge `json:",omitempty"`
148 | //}
149 |
150 | //func (g *Graph) RemoveNode(n *Node) {
151 |
152 | //}
153 |
154 | //func (g *Graph) RemoveEdge() {
155 |
156 | //}
157 |
--------------------------------------------------------------------------------
/graph/meta.go:
--------------------------------------------------------------------------------
1 | package graph //meta
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/emirpasic/gods/maps/treemap"
7 | )
8 |
9 | type Meta struct {
10 | Type *treemap.Map
11 | Data *treemap.Map
12 | }
13 |
14 | type MetaType struct {
15 | Type string
16 | Version string
17 | Author string
18 | Date time.Time
19 | }
20 |
21 | func NewMeta() *Meta {
22 | var m = &Meta{
23 | Type: treemap.NewWithIntComparator(),
24 | Data: treemap.NewWithIntComparator(),
25 | }
26 |
27 | return m
28 | }
29 |
30 | func (m *Meta) AddMeta(id int, i interface{}, t string, v string, a string, yr, mon, day int) {
31 |
32 | var mt = &MetaType{
33 | Type: t,
34 | Version: v,
35 | Author: a,
36 | Date: time.Time{},
37 | }
38 |
39 | mt.Date.AddDate(yr, mon, day)
40 |
41 | m.Type.Put(id, mt)
42 |
43 | m.Data.Put(id, i)
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/graphpanel/filelist.go:
--------------------------------------------------------------------------------
1 | package graphpanel
2 |
3 | import (
4 | "strings"
5 |
6 | "github.com/therecipe/qt/core"
7 | "github.com/therecipe/qt/gui"
8 | "github.com/therecipe/qt/widgets"
9 | )
10 |
11 | type Filelist struct{ *widgets.QListWidget }
12 |
13 | func (f *Filelist) KeyPressEvent(e *gui.QKeyEvent) {
14 |
15 | if e.Key() == int(core.Qt__Key_Delete) {
16 | f.TakeItem(f.CurrentRow())
17 | } else {
18 | view.KeyPressEventDefault(e)
19 | }
20 |
21 | }
22 |
23 | func (f *Filelist) CurrentItemChanged(current *widgets.QListWidgetItem, previous *widgets.QListWidgetItem) {
24 | txt := current.Text()
25 | LoadXML(txt)
26 | graphpanel.FileName.SetText(txt)
27 | }
28 |
29 | func (f *Filelist) DragEnterEvent_(e *gui.QDragEnterEvent) {
30 | e.AcceptProposedAction()
31 | }
32 |
33 | func (f *Filelist) DragMoveEvent_(e *gui.QDragMoveEvent) {
34 | e.AcceptProposedAction()
35 | }
36 |
37 | func (f *Filelist) DropEvent_(e *gui.QDropEvent) {
38 | e.SetDropAction(core.Qt__CopyAction)
39 | e.AcceptProposedAction()
40 | e.SetAccepted(true)
41 |
42 | font := gui.NewQFont2("verdana", 13, 1, false)
43 |
44 | for _, j := range strings.Split(e.MimeData().Text(), "\n") { // Urls()
45 | if j[len(j)-4:] == ".xml" {
46 | n := widgets.NewQListWidgetItem2(j[8:], f, 0)
47 | n.SetFont(font)
48 |
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/graphpanel/graphpanel.go:
--------------------------------------------------------------------------------
1 | package graphpanel
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/janus"
5 |
6 | "github.com/therecipe/qt/gui"
7 | "github.com/therecipe/qt/widgets"
8 | )
9 |
10 | var (
11 | LoadXML func(s string)
12 | GenXML func(s string)
13 | CanvasReset func()
14 | graphpanel *GraphPanel
15 | janusgraph *janus.Graph
16 | )
17 |
18 | type GraphPanel struct {
19 | *widgets.QDockWidget
20 | FileList Filelist
21 | FileName Lineedit
22 | GraphName Lineedit // QLineEdit
23 | JobID Lineedit
24 | DatasetPath Lineedit
25 | NodeID Lineedit
26 | Language Lineedit
27 | ScriptFile Lineedit
28 | ClassName Lineedit
29 | NodeList Nodelist // QListWidget
30 | EdgeIncoming *widgets.QTableWidget
31 | EdgeOutgoing *widgets.QTableWidget
32 | TblArgs *widgets.QTableView
33 | ValueList Valuelist
34 | GenerateXML *widgets.QPushButton
35 | }
36 |
37 | func NewGraphPanel(parent *widgets.QMainWindow, reset func(), lxml func(s string), genxml func(s string)) *GraphPanel {
38 |
39 | LoadXML = lxml
40 | GenXML = genxml
41 | CanvasReset = reset
42 |
43 | graphpanel = &GraphPanel{}
44 | graphpanel.QDockWidget = widgets.NewQDockWidget("Graph Panel", parent, 0)
45 |
46 | var w = widgets.NewQWidget(parent, 0)
47 | w.SetLayout(graphpanel.ui())
48 | graphpanel.SetWidget(w)
49 |
50 | return graphpanel
51 | }
52 |
53 | func (gp *GraphPanel) Clear() {
54 | gp.FileName.Clear()
55 | gp.GraphName.Clear()
56 | gp.JobID.Clear()
57 | gp.DatasetPath.Clear()
58 | gp.NodeID.Clear()
59 | gp.Language.Clear()
60 | gp.ScriptFile.Clear()
61 | gp.ClassName.Clear()
62 | gp.NodeList.Clear()
63 | gp.EdgeIncoming.Clear()
64 | gp.EdgeOutgoing.Clear()
65 | gp.Tblargs_Clear()
66 | //gp.TblArgs.Clear()
67 | gp.ValueList.Clear()
68 |
69 | }
70 |
71 | func (gp *GraphPanel) ui() *widgets.QVBoxLayout {
72 |
73 | var vlayout0 = widgets.NewQVBoxLayout()
74 |
75 | var lblFileset = widgets.NewQLabel2("File Set: ", nil, 0)
76 |
77 | gp.FileList = Filelist{widgets.NewQListWidget(nil)}
78 | gp.FileList.SetFont(gui.NewQFont2("verdana", 13, 1, false))
79 | gp.FileList.SetAcceptDrops(true)
80 | //gp.FileList.SetMaximumHeight(200)
81 |
82 | gp.FileList.ConnectDragEnterEvent(gp.FileList.DragEnterEvent_)
83 | gp.FileList.ConnectDragMoveEvent(gp.FileList.DragMoveEvent_)
84 | gp.FileList.ConnectDropEvent(gp.FileList.DropEvent_)
85 | gp.FileList.ConnectKeyPressEvent(gp.FileList.KeyPressEvent)
86 |
87 | gp.FileList.ConnectCurrentItemChanged(gp.FileList.CurrentItemChanged)
88 |
89 | vlayout0.AddWidget(lblFileset, 0, 0)
90 | vlayout0.AddWidget(gp.FileList, 0, 0)
91 |
92 | var hlayoutLine0 = widgets.NewQHBoxLayout()
93 |
94 | var lblFileName = widgets.NewQLabel2(" File Name: ", nil, 0)
95 | lblFileName.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
96 |
97 | gp.FileName = Lineedit{widgets.NewQLineEdit(nil)}
98 | gp.FileName.SetObjectName("FileName")
99 | gp.FileName.ConnectEditingFinished(gp.FileName.EditingFinished)
100 |
101 | gp.GenerateXML = widgets.NewQPushButton(nil)
102 | gp.GenerateXML.SetText("Save")
103 | gp.GenerateXML.SetMaximumWidth(150)
104 | gp.GenerateXML.ConnectClicked(func(_ bool) { GenXML(gp.FileName.Text()) })
105 |
106 | hlayoutLine0.AddWidget(lblFileName, 0, 0)
107 | hlayoutLine0.AddWidget(gp.FileName, 0, 0)
108 | hlayoutLine0.AddWidget(gp.GenerateXML, 0, 0)
109 |
110 | var hlayoutLine1 = gp.line1() // graph
111 | var hlayoutLine2 = gp.line2() // node
112 | var vlayoutLine3 = gp.line3() // arg
113 |
114 | var vlayout = widgets.NewQVBoxLayout()
115 |
116 | vlayout.AddLayout(vlayout0, 0)
117 | vlayout.AddLayout(hlayoutLine0, 0)
118 |
119 | vlayout.AddLayout(hlayoutLine1, 0)
120 | vlayout.AddLayout(hlayoutLine2, 0)
121 | vlayout.AddLayout(vlayoutLine3, 0)
122 |
123 | return vlayout
124 |
125 | }
126 |
127 | func (gp *GraphPanel) SetJanusGraph(j *janus.Graph) {
128 | janusgraph = j
129 | }
130 |
131 | func (gp *GraphPanel) line1() *widgets.QHBoxLayout {
132 | var gbGraphProperties = widgets.NewQGroupBox2("Graph Properties", nil)
133 |
134 | var vlayout = widgets.NewQVBoxLayout()
135 |
136 | var hlayoutLine1 = widgets.NewQHBoxLayout() // graphName, jobID
137 | var hlayoutLine2 = widgets.NewQHBoxLayout() // datasetPath
138 |
139 | var lblGraphName = widgets.NewQLabel2(" Graph Name: ", nil, 0)
140 | lblGraphName.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
141 |
142 | gp.GraphName = Lineedit{widgets.NewQLineEdit(nil)}
143 | gp.GraphName.SetObjectName("GraphName")
144 | gp.GraphName.ConnectEditingFinished(gp.GraphName.EditingFinished)
145 |
146 | var lblJobID = widgets.NewQLabel2(" Job ID: ", nil, 0)
147 | lblJobID.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
148 |
149 | gp.JobID = Lineedit{widgets.NewQLineEdit(nil)}
150 | gp.JobID.SetObjectName("JobID")
151 | gp.JobID.ConnectEditingFinished(gp.JobID.EditingFinished)
152 |
153 | var btnNewGraph = widgets.NewQPushButton(nil)
154 | btnNewGraph.SetText("New Graph")
155 | //btnScriptFile.SetMaximumWidth(120)
156 | btnNewGraph.ConnectClicked(func(_ bool) { CanvasReset() })
157 |
158 | var lblDatasetPath = widgets.NewQLabel2(" Dataset Path: ", nil, 0)
159 | lblDatasetPath.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
160 |
161 | gp.DatasetPath = Lineedit{widgets.NewQLineEdit(nil)}
162 | gp.DatasetPath.SetObjectName("DatasetPath")
163 | gp.DatasetPath.ConnectEditingFinished(gp.DatasetPath.EditingFinished)
164 |
165 | var vlayoutAlign = widgets.NewQVBoxLayout()
166 | var hlayoutAlign = widgets.NewQHBoxLayout()
167 |
168 | vlayoutAlign.AddWidget(lblGraphName, 0, 0)
169 | hlayoutLine1.AddWidget(gp.GraphName, 0, 0)
170 | hlayoutLine1.AddWidget(lblJobID, 0, 0)
171 | hlayoutLine1.AddWidget(gp.JobID, 0, 0)
172 | hlayoutLine1.AddWidget(btnNewGraph, 0, 0)
173 |
174 | vlayoutAlign.AddWidget(lblDatasetPath, 0, 0)
175 | hlayoutLine2.AddWidget(gp.DatasetPath, 0, 0)
176 |
177 | vlayout.AddLayout(hlayoutLine1, 0)
178 | vlayout.AddLayout(hlayoutLine2, 0)
179 |
180 | hlayoutAlign.AddLayout(vlayoutAlign, 0)
181 | hlayoutAlign.AddLayout(vlayout, 0)
182 |
183 | gbGraphProperties.SetLayout(hlayoutAlign)
184 |
185 | var hlayout = widgets.NewQHBoxLayout()
186 | hlayout.AddWidget(gbGraphProperties, 0, 0)
187 |
188 | return hlayout
189 |
190 | }
191 |
192 | func (gp *GraphPanel) line2() *widgets.QHBoxLayout {
193 |
194 | var hlayoutLine1 = widgets.NewQHBoxLayout() // nodeList
195 | var vlayoutLine2 = widgets.NewQVBoxLayout() // Node + Edges
196 | var hlayoutLine3 = widgets.NewQHBoxLayout() // List + Node/Edge
197 |
198 | var hlayoutLine21Node = widgets.NewQHBoxLayout() // Node
199 | var hlayoutLine22Edge = widgets.NewQHBoxLayout() // Edges
200 |
201 | // Node List
202 | gp.NodeList = Nodelist{widgets.NewQListWidget(nil)}
203 | gp.NodeList.ConnectCurrentItemChanged(gp.NodeList.CurrentItemChanged_)
204 |
205 | hlayoutLine1.AddWidget(gp.NodeList, 0, 0)
206 |
207 | //----------
208 | var gbNodeProperties = widgets.NewQGroupBox2("Node Properties", nil)
209 |
210 | var vlayout = widgets.NewQVBoxLayout()
211 |
212 | var hlayoutNpLine1 = widgets.NewQHBoxLayout() // nodeID, language
213 | var hlayoutNpLine2 = widgets.NewQHBoxLayout() // scriptfile
214 | var hlayoutNpLine3 = widgets.NewQHBoxLayout() // classname
215 |
216 | var lblNodeID = widgets.NewQLabel2(" Node ID: ", nil, 0)
217 | lblNodeID.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
218 |
219 | gp.NodeID = Lineedit{widgets.NewQLineEdit(nil)}
220 | gp.NodeID.SetObjectName("NodeID")
221 | gp.NodeID.ConnectEditingFinished(gp.NodeID.EditingFinished)
222 |
223 | var lblLanguage = widgets.NewQLabel2(" Language: ", nil, 0)
224 | lblLanguage.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
225 |
226 | gp.Language = Lineedit{widgets.NewQLineEdit(nil)}
227 | gp.Language.SetObjectName("Language")
228 | gp.Language.ConnectEditingFinished(gp.Language.EditingFinished)
229 |
230 | var lblScriptFile = widgets.NewQLabel2(" Script File: ", nil, 0)
231 | lblScriptFile.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
232 |
233 | gp.ScriptFile = Lineedit{widgets.NewQLineEdit(nil)}
234 | gp.ScriptFile.SetObjectName("ScriptFile")
235 | gp.ScriptFile.ConnectEditingFinished(gp.ScriptFile.EditingFinished)
236 |
237 | var lblClassName = widgets.NewQLabel2(" Class Name: ", nil, 0)
238 | lblClassName.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
239 |
240 | gp.ClassName = Lineedit{widgets.NewQLineEdit(nil)}
241 | gp.ClassName.SetObjectName("ClassName")
242 | gp.ClassName.ConnectEditingFinished(gp.ClassName.EditingFinished)
243 |
244 | var btnScriptFile = widgets.NewQPushButton(nil)
245 | btnScriptFile.SetText("+")
246 | btnScriptFile.SetMaximumWidth(35)
247 | btnScriptFile.ConnectClicked(func(_ bool) {
248 | if btnScriptFile.Text() == "+" {
249 | gp.EdgeIncoming.SetVisible(true)
250 | gp.EdgeOutgoing.SetVisible(true)
251 | btnScriptFile.SetText("-")
252 | } else {
253 | gp.EdgeOutgoing.SetVisible(false)
254 | gp.EdgeIncoming.SetVisible(false)
255 | btnScriptFile.SetText("+")
256 | }
257 |
258 | })
259 |
260 | var vlayoutAlign = widgets.NewQVBoxLayout()
261 | var hlayoutAlign = widgets.NewQHBoxLayout()
262 |
263 | vlayoutAlign.AddWidget(lblNodeID, 0, 0)
264 | hlayoutNpLine1.AddWidget(gp.NodeID, 0, 0)
265 | hlayoutNpLine1.AddWidget(lblLanguage, 0, 0)
266 | hlayoutNpLine1.AddWidget(gp.Language, 0, 0)
267 |
268 | vlayoutAlign.AddWidget(lblScriptFile, 0, 0)
269 | hlayoutNpLine2.AddWidget(gp.ScriptFile, 0, 0)
270 | hlayoutNpLine2.AddWidget(btnScriptFile, 0, 0)
271 |
272 | vlayoutAlign.AddWidget(lblClassName, 0, 0)
273 | hlayoutNpLine3.AddWidget(gp.ClassName, 0, 0)
274 |
275 | vlayout.AddLayout(hlayoutNpLine1, 0)
276 | vlayout.AddLayout(hlayoutNpLine2, 0)
277 | vlayout.AddLayout(hlayoutNpLine3, 0)
278 |
279 | hlayoutAlign.AddLayout(vlayoutAlign, 0)
280 | hlayoutAlign.AddLayout(vlayout, 0)
281 |
282 | gbNodeProperties.SetLayout(hlayoutAlign)
283 |
284 | hlayoutLine21Node.AddWidget(gbNodeProperties, 0, 0)
285 |
286 | // Incoming/Outgoing Edge Tables
287 | gp.EdgeIncoming = widgets.NewQTableWidget2(0, 1, nil)
288 | gp.EdgeOutgoing = widgets.NewQTableWidget2(0, 1, nil)
289 |
290 | gp.EdgeIncoming.SetVisible(false)
291 | gp.EdgeOutgoing.SetVisible(false)
292 |
293 | var strHeaders1 = []string{"Incoming Edge"}
294 | gp.EdgeIncoming.SetHorizontalHeaderLabels(strHeaders1)
295 | gp.EdgeIncoming.HorizontalHeader().SetStretchLastSection(true)
296 |
297 | var strHeaders2 = []string{"Outgoing Edge"}
298 | gp.EdgeOutgoing.SetHorizontalHeaderLabels(strHeaders2)
299 | gp.EdgeOutgoing.HorizontalHeader().SetStretchLastSection(true)
300 |
301 | hlayoutLine22Edge.AddWidget(gp.EdgeIncoming, 0, 0)
302 | hlayoutLine22Edge.AddWidget(gp.EdgeOutgoing, 0, 0)
303 |
304 | vlayoutLine2.AddLayout(hlayoutLine21Node, 0)
305 | vlayoutLine2.AddLayout(hlayoutLine22Edge, 0)
306 |
307 | var w1 = widgets.NewQWidget(nil, 0)
308 | var w2 = widgets.NewQWidget(nil, 0)
309 | var sp = widgets.NewQSplitter(nil)
310 |
311 | w1.SetLayout(hlayoutLine1)
312 | w2.SetLayout(vlayoutLine2)
313 | sp.AddWidget(w1)
314 | sp.AddWidget(w2)
315 |
316 | hlayoutLine3.AddWidget(sp, 0, 0)
317 |
318 | return hlayoutLine3
319 |
320 | }
321 |
322 | func (gp *GraphPanel) line3() *widgets.QVBoxLayout {
323 |
324 | var vlayout = widgets.NewQVBoxLayout()
325 |
326 | gp.TblArgs = NewArgsTable() // Args Table
327 |
328 | gp.ValueList = Valuelist{widgets.NewQListWidget(nil)}
329 | gp.ValueList.SetFont(gui.NewQFont2("verdana", 13, 1, false))
330 | gp.ValueList.SetAcceptDrops(true)
331 |
332 | gp.ValueList.ConnectDragEnterEvent(gp.ValueList.DragEnterEvent_)
333 | gp.ValueList.ConnectDragMoveEvent(gp.ValueList.DragMoveEvent_)
334 | gp.ValueList.ConnectDropEvent(gp.ValueList.DropEvent_)
335 |
336 | var sp = widgets.NewQSplitter(nil)
337 | sp.SetOrientation(2)
338 | sp.AddWidget(gp.TblArgs)
339 | sp.AddWidget(gp.ValueList)
340 |
341 | vlayout.AddWidget(sp, 0, 0)
342 |
343 | return vlayout
344 |
345 | }
346 |
--------------------------------------------------------------------------------
/graphpanel/lineedit.go:
--------------------------------------------------------------------------------
1 | package graphpanel
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/janus"
5 |
6 | "github.com/therecipe/qt/core"
7 | "github.com/therecipe/qt/widgets"
8 | )
9 |
10 | type Lineedit struct{ *widgets.QLineEdit }
11 |
12 | func (l *Lineedit) EditingFinished() {
13 |
14 | var di = graphpanel.NodeList.CurrentItem().Data(int(core.Qt__UserRole)).ToInt(true)
15 |
16 | i, _ := janusgraph.Nodes.Get(di)
17 | jn := i.(*janus.Node)
18 |
19 | switch l.ObjectName() {
20 |
21 | case "GraphName":
22 | janusgraph.GraphName = l.Text()
23 |
24 | case "JobID":
25 | janusgraph.JobID = l.Text()
26 |
27 | case "DatasetPath":
28 | janusgraph.DatasetPath = l.Text()
29 |
30 | case "NodeID":
31 | jn.NodeID = l.Text()
32 |
33 | case "Language":
34 | jn.Language = l.Text()
35 |
36 | case "ScriptFile":
37 | jn.ScriptFile = l.Text()
38 |
39 | case "ClassName":
40 | jn.ClassName = l.Text()
41 | // update canvas and list names
42 | graphpanel.NodeList.CurrentItem().SetText(l.Text())
43 | // f, _ := canvas.Figures.Get(di)
44 | // r := f.(*rectangle.Rectangle)
45 | // r.Name = l.Text()
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/graphpanel/nodelist.go:
--------------------------------------------------------------------------------
1 | package graphpanel
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/janus"
5 |
6 | "github.com/therecipe/qt/core"
7 | "github.com/therecipe/qt/gui"
8 | "github.com/therecipe/qt/widgets"
9 | )
10 |
11 | type Nodelist struct{ *widgets.QListWidget }
12 |
13 | func (n *Nodelist) CurrentItemChanged_(current *widgets.QListWidgetItem, previous *widgets.QListWidgetItem) {
14 |
15 | var di = current.Data(int(core.Qt__UserRole)).ToInt(true)
16 | jn, _ := janusgraph.Nodes.Get(di)
17 | i := jn.(*janus.Node)
18 |
19 | graphpanel.NodeID.SetText(i.NodeID)
20 | graphpanel.Language.SetText(i.Language)
21 | graphpanel.ScriptFile.SetText(i.ScriptFile)
22 | graphpanel.ClassName.SetText(i.ClassName)
23 |
24 | graphpanel.EdgeIncoming.ClearContents()
25 | graphpanel.EdgeIncoming.SetRowCount(i.AntiEdges.Size())
26 | graphpanel.EdgeOutgoing.ClearContents()
27 | graphpanel.EdgeOutgoing.SetRowCount(i.Edges.Size())
28 |
29 | font := gui.NewQFont2("verdana", 13, 1, false)
30 |
31 | for indx, x := range i.Edges.Values() {
32 | xi := x.(*janus.Edge)
33 | var wi = widgets.NewQTableWidgetItem2(xi.String, 0)
34 | wi.SetFont(font)
35 | graphpanel.EdgeOutgoing.SetItem(indx, 0, wi)
36 | }
37 |
38 | for indx, x := range i.AntiEdges.Values() {
39 | xi := x.(*janus.Edge)
40 | var wi = widgets.NewQTableWidgetItem2(xi.String, 0)
41 | wi.SetFont(font)
42 | graphpanel.EdgeIncoming.SetItem(indx, 0, wi)
43 | }
44 |
45 | // ARGS Table
46 | ClearAndSetModel(i) // .(*janus.Node) current
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/graphpanel/tblargs.go:
--------------------------------------------------------------------------------
1 | package graphpanel
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/janus"
5 |
6 | "strconv"
7 |
8 | "github.com/emirpasic/gods/maps/treemap"
9 | "github.com/therecipe/qt/core"
10 | "github.com/therecipe/qt/gui"
11 | "github.com/therecipe/qt/widgets"
12 | )
13 |
14 | var (
15 | model *core.QAbstractTableModel // QAbstractItemModel
16 | view *widgets.QTableView
17 |
18 | textIndex *core.QModelIndex
19 | currentRow int
20 | currentNode *janus.Node
21 | currentArg *janus.Arg
22 | previousRow int //?
23 | )
24 |
25 | type Delegate struct {
26 | widgets.QStyledItemDelegate //don't use *pointers or it won't work
27 | }
28 |
29 | type Tblargs struct{ *widgets.QTableView }
30 |
31 | func NewArgsTable() *widgets.QTableView {
32 | view = widgets.NewQTableView(nil) // setObjectName
33 | model = core.NewQAbstractTableModel(nil) // NewQAbstractItemModel(nil)
34 |
35 | delegate := InitDelegate()
36 | view.SetItemDelegate(delegate)
37 | //view.SetItemDelegateForColumn(0, delegate)
38 | view.SetFont(gui.NewQFont2("verdana", 13, 1, false))
39 |
40 | view.SetColumnWidth(1, 250)
41 | view.HorizontalHeader().SetStretchLastSection(true)
42 |
43 | view.SetSelectionBehavior(0) // SelectItems
44 | view.SetSelectionMode(1) // SingleSelection
45 |
46 | view.ConnectKeyPressEvent(view_keypressevent)
47 | //view.ConnectCurrentChanged(view_currentchanged)
48 | view.ConnectSelectionChanged(view_selectionchanged)
49 |
50 | model.ConnectRowCount(model_rowcount)
51 | model.ConnectColumnCount(model_columncount)
52 | model.ConnectData(model_data)
53 | model.ConnectSetData(model_setdata)
54 | model.ConnectInsertRows(model_insertrows)
55 | model.ConnectFlags(model_flags)
56 | model.ConnectRemoveRows(model_removerows)
57 | model.ConnectHeaderData(model_headerdata)
58 |
59 | view.SetModel(model)
60 |
61 | return view
62 | }
63 |
64 | func (gp *GraphPanel) Tblargs_Clear() {
65 | model.BeginResetModel()
66 | //gp.TblArgs = NewArgsTable() //Reset()
67 | model.EndResetModel()
68 | //SetModel()
69 |
70 | graphpanel.ValueList.Clear()
71 | }
72 |
73 | func ClearAndSetModel(jn *janus.Node) { // current Node treemap - called when node in nodelist selected
74 | //model.Clear()
75 | model.BeginResetModel()
76 | model.EndResetModel()
77 |
78 | currentNode = jn
79 | graphpanel.ValueList.Clear()
80 |
81 | currentRow = 0
82 | a, _ := currentNode.Args.Get(currentRow)
83 | currentArg = a.(*janus.Arg)
84 |
85 | // valuelist
86 | font := gui.NewQFont2("verdana", 13, 1, false)
87 | for _, x := range currentArg.Values.Values() {
88 |
89 | xj := x.(string)
90 | n := widgets.NewQListWidgetItem2(xj, graphpanel.ValueList, 0)
91 | n.SetFont(font)
92 | }
93 |
94 | graphpanel.TblArgs.SelectRow(0)
95 |
96 | }
97 |
98 | func view_keypressevent(e *gui.QKeyEvent) {
99 | if e.Key() == int(core.Qt__Key_Delete) {
100 | if view.CurrentIndex().Row() < currentNode.Args.Size()-1 {
101 | // statusbar.ShowMessage("row: "+strconv.Itoa(currentRow)+" list size: "+strconv.Itoa(listv.Size()), 0)
102 | model.RemoveRows(view.CurrentIndex().Row(), 1, core.NewQModelIndex())
103 | updateValuelist()
104 | }
105 | } else {
106 | view.KeyPressEventDefault(e)
107 | }
108 | }
109 |
110 | //func view_currentchanged(current *core.QModelIndex, previous *core.QModelIndex) {
111 | // previousRow = previous.Row()
112 | // currentRow = current.Row()
113 | //}
114 |
115 | func view_selectionchanged(selected *core.QItemSelection, deselected *core.QItemSelection) {
116 | updateValuelist()
117 | }
118 |
119 | func updateValuelist() {
120 | graphpanel.ValueList.Clear()
121 | // clear and update valuelist w/ jgraph
122 | // current args list row
123 | var r = view.CurrentIndex().Row()
124 | a, _ := currentNode.Args.Get(r)
125 | currentArg := a.(*janus.Arg)
126 |
127 | for _, x := range currentArg.Values.Values() {
128 | xj := x.(string)
129 | widgets.NewQListWidgetItem2(xj, graphpanel.ValueList, 0)
130 | }
131 | }
132 |
133 | func InitDelegate() *Delegate {
134 | item := NewDelegate(nil) //will be generated in moc.go
135 | item.ConnectCreateEditor(delegate_createEditor)
136 | item.ConnectSetEditorData(delegate_setEditorData)
137 | item.ConnectSetModelData(delegate_setModelData)
138 | item.ConnectUpdateEditorGeometry(delegate_updateEditorGeometry)
139 | return item
140 | }
141 |
142 | func delegate_createEditor(parent *widgets.QWidget, option *widgets.QStyleOptionViewItem, index *core.QModelIndex) *widgets.QWidget {
143 | editor := widgets.NewQLineEdit(parent)
144 | textIndex = index //?
145 |
146 | if index.Row() == currentNode.Args.Size()-1 {
147 | model.InsertRow(index.Row(), core.NewQModelIndex())
148 | }
149 |
150 | //editor.ConnectTextChanged(delegate_textchanged)
151 |
152 | return editor.QWidget_PTR()
153 | }
154 |
155 | // not needed??
156 | func delegate_textchanged(text string) {
157 | model.SetData(textIndex, core.NewQVariant14(text), 2) // edit role = 2
158 | }
159 |
160 | func delegate_setEditorData(editor *widgets.QWidget, index *core.QModelIndex) {
161 | var value string
162 |
163 | //currentRow = index.Row() // needed?
164 | var argi, exists = currentNode.Args.Get(index.Row())
165 |
166 | currentArg = argi.(*janus.Arg) // needed??
167 |
168 | if exists {
169 | //var arg = argi.(*janus.Arg)
170 | switch index.Column() {
171 | case 0:
172 | value = currentArg.Source
173 | case 1:
174 | value = currentArg.Value
175 | }
176 | }
177 |
178 | lineedit := widgets.NewQLineEditFromPointer(editor.Pointer())
179 | lineedit.SetText(value) //.(string)
180 | }
181 |
182 | func delegate_setModelData(editor *widgets.QWidget, model *core.QAbstractItemModel, index *core.QModelIndex) {
183 | lineedit := widgets.NewQLineEditFromPointer(editor.Pointer())
184 | text := lineedit.Text()
185 | model.SetData(index, core.NewQVariant14(text), int(core.Qt__EditRole))
186 | }
187 |
188 | func delegate_updateEditorGeometry(editor *widgets.QWidget, option *widgets.QStyleOptionViewItem, index *core.QModelIndex) {
189 | editor.SetGeometry(option.Rect())
190 | }
191 |
192 | func model_headerdata(section int, orientation core.Qt__Orientation, role int) *core.QVariant {
193 | if orientation == 1 && role == 0 { // Qt__Horizontal, Qt__DisplayRole
194 | switch section {
195 | case 0:
196 | return core.NewQVariant14("Source")
197 | case 1:
198 | return core.NewQVariant14("Value")
199 | }
200 |
201 | return core.NewQVariant14("column" + strconv.Itoa(section+1))
202 | }
203 |
204 | if orientation == 2 && role == 0 {
205 | if section < currentNode.Args.Size()-1 {
206 | return core.NewQVariant14(strconv.Itoa(section + 1))
207 | } else {
208 | return core.NewQVariant14("*")
209 | }
210 | }
211 | return core.NewQVariant()
212 | }
213 |
214 | func model_rowcount(parent *core.QModelIndex) int {
215 | return currentNode.Args.Size() //+ 1
216 | }
217 |
218 | func model_columncount(parent *core.QModelIndex) int {
219 | return 2
220 | }
221 |
222 | func model_data(index *core.QModelIndex, role int) *core.QVariant { // dataset to model/view
223 |
224 | if role == 0 && index.IsValid() { // display role = 0
225 |
226 | var argi, exists = currentNode.Args.Get(index.Row())
227 |
228 | if exists {
229 | var arg = argi.(*janus.Arg)
230 | switch index.Column() {
231 | case 0:
232 | return core.NewQVariant14(arg.Source)
233 | case 1:
234 | return core.NewQVariant14(arg.Value)
235 | }
236 | }
237 | }
238 | return core.NewQVariant()
239 |
240 | }
241 |
242 | func model_setdata(index *core.QModelIndex, value *core.QVariant, role int) bool { // model/view to dataset
243 | if (role == 2 || role == 0) && index.IsValid() { // edit role = 2
244 |
245 | var argi, exists = currentNode.Args.Get(index.Row())
246 |
247 | if exists {
248 | var arg = argi.(*janus.Arg)
249 | //if !(arg.Source == "" && arg.Value == "") {
250 | switch index.Column() {
251 | case 0:
252 | currentNode.Args.Put(index.Row(), &janus.Arg{Source: value.ToString(), Value: arg.Value, Values: arg.Values})
253 | case 1:
254 | currentNode.Args.Put(index.Row(), &janus.Arg{Source: arg.Source, Value: value.ToString(), Values: arg.Values})
255 | }
256 | return true
257 | }
258 | }
259 | return true
260 | }
261 |
262 | func model_insertrows(row int, count int, parent *core.QModelIndex) bool {
263 | model.BeginInsertRows(core.NewQModelIndex(), row, row)
264 |
265 | currentNode.Args.Put(row+1, &janus.Arg{Source: "", Values: treemap.NewWithIntComparator()})
266 |
267 | model.EndInsertRows()
268 | view.SelectRow(row)
269 | return true
270 | }
271 |
272 | func model_removerows(row int, count int, parent *core.QModelIndex) bool {
273 | model.BeginRemoveRows(core.NewQModelIndex(), row, row)
274 |
275 | currentNode.Args.Remove(row)
276 |
277 | // reset indexes
278 | for i, x := range currentNode.Args.Keys() { // i always starts from zero
279 | indx := x.(int) // indx does not
280 |
281 | if indx != i {
282 | var ar, _ = currentNode.Args.Get(indx)
283 | var arg = ar.(*janus.Arg)
284 | currentNode.Args.Put(i, &janus.Arg{Source: arg.Source, Value: arg.Value, Values: arg.Values})
285 | currentNode.Args.Remove(indx)
286 | }
287 |
288 | }
289 |
290 | model.EndRemoveRows()
291 | return true
292 |
293 | }
294 |
295 | func model_flags(index *core.QModelIndex) core.Qt__ItemFlag {
296 | return 35 // 1 || 2 || 32 // ItemIsSelectable || ItemIsEditable || ItemIsEnabled
297 | }
298 |
299 | //func (ta *Tblargs) ItemChanged_(current *widgets.QTableWidgetItem) {
300 | // var di = graphpanel.NodeList.CurrentItem().Data(int(core.Qt__UserRole)).ToInt(true)
301 | // i, _ := janusgraph.Nodes.Get(di)
302 | // jn := i.(*janus.Node)
303 |
304 | // wit := current.Text()
305 | // currentRow := current.Row()
306 | // currentColumn := current.Column()
307 |
308 | // for indx, x := range jn.Args.Values() {
309 | // xi := x.(*janus.Arg)
310 |
311 | // if currentRow == indx {
312 | // switch currentColumn {
313 | // case 1: // Source
314 | // xi.Source = wit
315 |
316 | // case 2: // Value
317 | // xi.Value = wit
318 |
319 | // }
320 | // }
321 |
322 | // }
323 |
324 | //}
325 |
326 | //func (ta *Tblargs) CurrentCellChanged(currentRow int, currentColumn int, previousRow int, previousColumn int) {
327 | // var di = graphpanel.NodeList.CurrentItem().Data(int(core.Qt__UserRole)).ToInt(true)
328 | // i, _ := janusgraph.Nodes.Get(di)
329 | // jn := i.(*janus.Node)
330 |
331 | // wit := ta.Item(currentRow, currentColumn).Text()
332 |
333 | // for indx, x := range jn.Args.Values() {
334 | // xi := x.(*janus.Arg)
335 |
336 | // if currentRow == indx {
337 | // switch currentColumn {
338 | // case 1: // Source
339 | // xi.Source = wit
340 |
341 | // case 2: // Value
342 | // xi.Value = wit
343 |
344 | // }
345 | // }
346 |
347 | // }
348 |
349 | //}
350 |
351 | // var wi = widgets.NewQTableWidgetItem2(xi.Source, 0)
352 | // wi.SetFont(font)
353 | // graphpanel.TblArgs.SetItem(indx, 1, wi)
354 |
355 | // for _, x := range xi.Value.Values() {
356 | // xi := x.(string)
357 |
358 | // if xi != "" {
359 | // n := widgets.NewQListWidgetItem2(xi, graphpanel.ValueList, 0)
360 | // n.SetFont(font)
361 | // }
362 |
363 | // }
364 |
365 | //https://github.com/RustamSafiulin/mnemo_designer/blob/478e34be3564d3c51d8fae7aac9b3c820c6bc12c/propertyeditor/propertytableview.cpp
366 | //void PropertyTableView::init() {
367 |
368 | // resizeColumnsToContents();
369 | // setColumnWidth(0,150);
370 | // setAlternatingRowColors(true);
371 | // setSelectionMode(QTableView::SingleSelection);
372 | // setSelectionBehavior(QTableView::SelectRows);
373 | // setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::SelectedClicked);
374 | // verticalHeader()->hide();
375 | // verticalHeader()->setDefaultSectionSize(25);
376 | // horizontalHeader()->setStretchLastSection(true);
377 |
378 | // delegate = new PropertyDelegate(this);
379 | // setItemDelegate(delegate);
380 | //}
381 |
--------------------------------------------------------------------------------
/graphpanel/valuelist.go:
--------------------------------------------------------------------------------
1 | package graphpanel
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/janus"
5 | "strings"
6 |
7 | "github.com/therecipe/qt/core"
8 | "github.com/therecipe/qt/gui"
9 | "github.com/therecipe/qt/widgets"
10 | )
11 |
12 | type Valuelist struct{ *widgets.QListWidget }
13 |
14 | func (v *Valuelist) DragEnterEvent_(e *gui.QDragEnterEvent) {
15 | e.AcceptProposedAction()
16 | }
17 |
18 | func (v *Valuelist) DragMoveEvent_(e *gui.QDragMoveEvent) {
19 | e.AcceptProposedAction()
20 | }
21 |
22 | func (v *Valuelist) DropEvent_(e *gui.QDropEvent) {
23 | e.SetDropAction(core.Qt__CopyAction)
24 | e.AcceptProposedAction()
25 | e.SetAccepted(true)
26 |
27 | font := gui.NewQFont2("verdana", 13, 1, false)
28 |
29 | // current node
30 | var di = graphpanel.NodeList.CurrentItem().Data(int(core.Qt__UserRole)).ToInt(true)
31 | ji, _ := janusgraph.Nodes.Get(di)
32 | jn := ji.(*janus.Node)
33 |
34 | // current args list row
35 | var r = view.CurrentIndex().Row()
36 | a, _ := jn.Args.Get(r)
37 |
38 | ja := a.(*janus.Arg)
39 | ja.Values.Clear()
40 |
41 | // write list items and j.Arg.Values
42 | for indx, j := range strings.Split(e.MimeData().Text(), "\n") { // Urls()
43 | if j != "" {
44 | n := widgets.NewQListWidgetItem2(j[8:], v, 0)
45 | n.SetFont(font)
46 |
47 | ja.Values.Put(indx, j[8:])
48 |
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/images/New folder/eraser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/New folder/eraser.png
--------------------------------------------------------------------------------
/images/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/circle.png
--------------------------------------------------------------------------------
/images/cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/cursor.png
--------------------------------------------------------------------------------
/images/eraser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/eraser.png
--------------------------------------------------------------------------------
/images/grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/grid.png
--------------------------------------------------------------------------------
/images/hand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/hand.png
--------------------------------------------------------------------------------
/images/line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/line.png
--------------------------------------------------------------------------------
/images/pen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/pen.png
--------------------------------------------------------------------------------
/images/sizeall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/sizeall.png
--------------------------------------------------------------------------------
/images/square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/square.png
--------------------------------------------------------------------------------
/images/square.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
75 |
--------------------------------------------------------------------------------
/images/type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/5k3105/Pipeline-Editor/3b9fe75d83b6d0df95a70ccc337f105b2f98c8cc/images/type.png
--------------------------------------------------------------------------------
/janus/janus.go:
--------------------------------------------------------------------------------
1 | package janus
2 |
3 | import (
4 | "strconv"
5 |
6 | "github.com/emirpasic/gods/maps/treemap"
7 | )
8 |
9 | var graph *Graph
10 |
11 | type Graph struct {
12 | GraphName string
13 | DatasetPath string
14 | JobID string
15 | Nodes *treemap.Map
16 | }
17 |
18 | type Node struct {
19 | NodeID string
20 | Language string
21 | ScriptFile string
22 | ClassName string
23 | Args *treemap.Map
24 | Edges *treemap.Map
25 | AntiEdges *treemap.Map
26 | X, Y float64
27 | }
28 |
29 | type Arg struct {
30 | Source string
31 | Value string
32 | Values *treemap.Map
33 | }
34 |
35 | type Edge struct {
36 | String string
37 | }
38 |
39 | func NewJanusGraph() *Graph {
40 | graph = &Graph{Nodes: treemap.NewWithIntComparator()}
41 | return graph
42 | }
43 |
44 | func (jg *Graph) AddNode(i int, x, y float64) {
45 | jg.Nodes.Put(i, &Node{NodeID: strconv.Itoa(i),
46 | Language: "python",
47 | ClassName: "node " + strconv.Itoa(i),
48 | Args: treemap.NewWithIntComparator(),
49 | Edges: treemap.NewWithIntComparator(),
50 | AntiEdges: treemap.NewWithIntComparator(),
51 | X: x,
52 | Y: y})
53 |
54 | in, _ := jg.Nodes.Get(i)
55 | n := in.(*Node)
56 | n.AddArg(0)
57 | }
58 |
59 | func (jg *Graph) AddNodeFromFile(i int, x, y float64, language, classname, scriptfile string) {
60 | jg.Nodes.Put(i, &Node{
61 | NodeID: strconv.Itoa(i),
62 | Language: language,
63 | ClassName: classname,
64 | ScriptFile: scriptfile,
65 | Args: treemap.NewWithIntComparator(),
66 | Edges: treemap.NewWithIntComparator(),
67 | AntiEdges: treemap.NewWithIntComparator(),
68 | X: x,
69 | Y: y})
70 |
71 | in, _ := jg.Nodes.Get(i)
72 | n := in.(*Node)
73 | n.AddArg(0)
74 | }
75 |
76 | func (jg *Graph) RemoveNode(i int) {
77 | jg.Nodes.Remove(i)
78 |
79 | }
80 |
81 | func (n *Node) AddEdge(i int, t string) {
82 | switch t {
83 | case "Incoming Edge":
84 | n.Edges.Put(i, &Edge{String: strconv.Itoa(i)}) // edge is using i as key and value
85 | case "Outgoing Edge":
86 | n.AntiEdges.Put(i, &Edge{String: strconv.Itoa(i)})
87 | }
88 |
89 | }
90 |
91 | func (n *Node) RemoveEdge(i int, t string) {
92 | switch t {
93 | case "Incoming Edge":
94 | n.Edges.Remove(i)
95 | case "Outgoing Edge":
96 | n.AntiEdges.Remove(i)
97 | }
98 |
99 | }
100 |
101 | func (n *Node) RemoveEdges() {
102 |
103 | // n.Edges.Remove(i)
104 |
105 | // n.AntiEdges.Remove(i)
106 |
107 | }
108 |
109 | func (n *Node) AddArg(i int) {
110 | n.Args.Put(i, &Arg{Source: "", Values: treemap.NewWithIntComparator()})
111 | }
112 |
113 | func (n *Node) RemoveArg(i int) {
114 | n.Args.Remove(i)
115 | }
116 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/5k3105/Pipeline-Editor/genxml"
5 | "github.com/5k3105/Pipeline-Editor/gfxcanvas"
6 | "github.com/5k3105/Pipeline-Editor/gfxobjects/rectangle"
7 | "github.com/5k3105/Pipeline-Editor/graphpanel"
8 | "github.com/5k3105/Pipeline-Editor/janus"
9 | "os"
10 |
11 | "github.com/therecipe/qt/core"
12 | "github.com/therecipe/qt/gui"
13 | "github.com/therecipe/qt/widgets"
14 | )
15 |
16 | type Application struct {
17 | *widgets.QApplication
18 | Window *widgets.QMainWindow
19 | Canvas *gfxcanvas.Canvas
20 | GraphPanel *graphpanel.GraphPanel
21 | Statusbar *widgets.QStatusBar
22 | }
23 |
24 | func main() {
25 | var ap = &Application{}
26 | ap.QApplication = widgets.NewQApplication(len(os.Args), os.Args)
27 |
28 | ap.Window = widgets.NewQMainWindow(nil, 0)
29 | ap.Window.SetWindowTitle("Pipeline Editor")
30 |
31 | ap.Statusbar = widgets.NewQStatusBar(ap.Window)
32 | ap.Window.SetStatusBar(ap.Statusbar)
33 |
34 | ap.GraphPanel = graphpanel.NewGraphPanel(ap.Window, ap.CanvasReset, ap.LoadXML, ap.GenXML)
35 | ap.GraphPanel.SetMinimumWidth(320)
36 |
37 | ap.Canvas = gfxcanvas.NewCanvas(ap.Window, ap.ListNodes)
38 | ap.Canvas.Statusbar = ap.Statusbar
39 |
40 | ap.GraphPanel.SetJanusGraph(ap.Canvas.JanusGraph)
41 |
42 | ap.Window.AddDockWidget(core.Qt__LeftDockWidgetArea, ap.GraphPanel)
43 | ap.Window.SetCentralWidget(ap.Canvas.View)
44 |
45 | ap.Statusbar.ShowMessage(core.QCoreApplication_ApplicationDirPath(), 0)
46 |
47 | widgets.QApplication_SetStyle2("fusion")
48 | ap.Window.ShowMaximized()
49 | widgets.QApplication_Exec()
50 | }
51 |
52 | func (ap *Application) CanvasReset() {
53 | ap.Canvas = gfxcanvas.NewCanvas(ap.Window, ap.ListNodes)
54 | ap.Canvas.Statusbar = ap.Statusbar
55 | ap.Window.SetCentralWidget(ap.Canvas.View)
56 | ap.GraphPanel.SetJanusGraph(ap.Canvas.JanusGraph)
57 |
58 | // point := core.NewQPointF3(300, 300)
59 | // ap.Canvas.View.CenterOn(point)
60 |
61 | ap.GraphPanel.Clear()
62 | }
63 |
64 | func (ap *Application) GenXML(filename string) {
65 | genxml.GenXML(ap.GraphPanel, ap.Canvas.JanusGraph, filename)
66 | }
67 |
68 | func (ap *Application) LoadXML(filename string) {
69 | //ap.Canvas.Reset()
70 | ap.CanvasReset()
71 | genxml.LoadXML(filename, ap.Canvas, ap.GraphPanel)
72 | ap.ListNodes()
73 |
74 | // hack
75 | var strHeaders1 = []string{"Incoming Edge"}
76 | ap.GraphPanel.EdgeIncoming.SetHorizontalHeaderLabels(strHeaders1)
77 | ap.GraphPanel.EdgeIncoming.HorizontalHeader().SetStretchLastSection(true)
78 |
79 | var strHeaders2 = []string{"Outgoing Edge"}
80 | ap.GraphPanel.EdgeOutgoing.SetHorizontalHeaderLabels(strHeaders2)
81 | ap.GraphPanel.EdgeOutgoing.HorizontalHeader().SetStretchLastSection(true)
82 |
83 | ap.GraphPanel.NodeList.SetCurrentRow(0)
84 |
85 | // point := core.NewQPointF3(300, 300)
86 | // ap.Canvas.View.CenterOn(point)
87 | }
88 |
89 | func (ap *Application) TextUpdate() { // update text from tblargs to rect font
90 |
91 | }
92 |
93 | func (ap *Application) ListNodes() {
94 | ap.GraphPanel.NodeList.Clear()
95 |
96 | font := gui.NewQFont2("verdana", 13, 1, false)
97 |
98 | for _, f := range ap.Canvas.Figures.Values() {
99 | r := f.(*rectangle.Rectangle)
100 |
101 | ij, _ := ap.Canvas.JanusGraph.Nodes.Get(r.Node.Id)
102 | n := ij.(*janus.Node)
103 |
104 | var txt = n.ClassName
105 | r.Name = n.ClassName
106 |
107 | var li = widgets.NewQListWidgetItem2(txt, ap.GraphPanel.NodeList, 0)
108 | li.SetFont(font)
109 | li.SetData(int(core.Qt__UserRole), core.NewQVariant7(r.Node.Id))
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------