From 296ec8a94bbcb2e0d327d852c1b2f85ad9b733f8 Mon Sep 17 00:00:00 2001 From: lordwelch Date: Sun, 27 Mar 2016 13:01:51 -0700 Subject: [PATCH] resstructure --- glfw.go | 163 ++++++++++++++++++ magickwand.go => imagick.go | 41 +++-- imgprovider.go | 23 --- main.go | 325 ++---------------------------------- main.qml | 9 + qml.go | 162 ++++++++++++++++++ xml.go | 1 + 7 files changed, 376 insertions(+), 348 deletions(-) create mode 100644 glfw.go rename magickwand.go => imagick.go (64%) delete mode 100644 imgprovider.go create mode 100644 qml.go diff --git a/glfw.go b/glfw.go new file mode 100644 index 0000000..c5829aa --- /dev/null +++ b/glfw.go @@ -0,0 +1,163 @@ +// PresentationApp project glfw.go +package main + +import ( + "fmt" + "image" + "log" + + "github.com/go-gl/gl/v2.1/gl" + "github.com/go-gl/glfw/v3.1/glfw" + "github.com/lordwelch/qml" +) + +var ( + win *glfw.Window + monWidth int //displayed height + monHeight int //displayed width + monitors []*glfw.Monitor + projMonitor *glfw.Monitor + tex1 *uint32 //identifier for opengl texture + texDel Bool //if texture should be deleted +) + +func setupScene() { + + gl.ClearColor(0, 0, 0, 0) + if texDel { + gl.DeleteTextures(1, tex1) + } + tex1 = newTexture(*slides[selCell].getImage(monWidth, monHeight)) + + gl.MatrixMode(gl.PROJECTION) + gl.LoadIdentity() + gl.Ortho(-1, 1, -1, 1, 1.0, 10.0) + gl.MatrixMode(gl.MODELVIEW) + gl.LoadIdentity() + texDel = true + +} + +func drawSlide() { + gl.Clear(gl.COLOR_BUFFER_BIT) + + gl.MatrixMode(gl.MODELVIEW) + gl.LoadIdentity() + gl.Translatef(0, 0, -3.0) + + gl.Begin(gl.QUADS) + + //top left + gl.TexCoord2f(0, 0) + gl.Vertex3f(-1, 1, 0) + //top right + gl.TexCoord2f(1, 0) + gl.Vertex3f(1, 1, 0) + + //bottom right + gl.TexCoord2f(1, 1) + gl.Vertex3f(1, -1, 0) + + //bottom left + gl.TexCoord2f(0, 1) + gl.Vertex3f(-1, -1, 0) + + gl.End() + +} + +func newTexture(rgba image.RGBA) *uint32 { + var texture1 uint32 + gl.Enable(gl.TEXTURE_2D) + gl.GenTextures(1, &texture1) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) + gl.TexImage2D( + gl.TEXTURE_2D, + 0, + gl.RGBA, + int32(rgba.Rect.Size().X), + int32(rgba.Rect.Size().Y), + 0, + gl.RGBA, + gl.UNSIGNED_BYTE, + gl.Ptr(rgba.Pix)) + + return &texture1 + +} + +func checkMon() { + monitors = glfw.GetMonitors() + glfw.WindowHint(glfw.ContextVersionMajor, 2) + glfw.WindowHint(glfw.ContextVersionMinor, 1) + glfw.WindowHint(glfw.AutoIconify, glfw.False) + glfw.WindowHint(glfw.Decorated, glfw.False) + + if i := len(monitors); i < 2 { + fmt.Println("You only have 1 monitor!!!!!!!!!!! :-P") + monWidth = 800 + monHeight = 600 + + win, err = glfw.CreateWindow(monWidth, monHeight, "Cube", nil, nil) + if err != nil { + panic(err) + } + projMonitor = monitors[0] + } else { + fmt.Printf("You have %d monitors\n", i) + monWidth = monitors[1].GetVideoMode().Width + monHeight = monitors[1].GetVideoMode().Height + win, err = glfw.CreateWindow(monWidth, monHeight, "Cube", nil, nil) + win.SetPos(monitors[1].GetPos()) + fmt.Printf("Width: %d Height: %d \n",monWidth, monHeight) + if err != nil { + panic(err) + } + projMonitor = monitors[1] + + } + monitorInfo() + +} + +func monitorInfo() { + for _, mon := range monitors { + fmt.Printf("monitor name: %s\n", mon.GetName()) + i, t := mon.GetPos() + fmt.Printf("position X: %d Y: %d\n", i, t) + + } + +} + +func glInit() { + window.Set("cls", false) + if err = glfw.Init(); err != nil { + log.Fatalln("failed to initialize glfw:", err) + } + checkMon() + + win.MakeContextCurrent() + + if err := gl.Init(); err != nil { + panic(err) + } + + win.SetPos(projMonitor.GetPos()) + setupScene() + + qml.Func1 = func() int { + if !win.ShouldClose() { + glfw.PollEvents() + drawSlide() + win.SwapBuffers() + return 0 + + } + win.Hide() + win.Destroy() + glfw.Terminate() + return 1 + + } +} diff --git a/magickwand.go b/imagick.go similarity index 64% rename from magickwand.go rename to imagick.go index 984eb8b..2bce974 100644 --- a/magickwand.go +++ b/imagick.go @@ -1,8 +1,9 @@ -// magickwand.go +// PresentationApp project imagick.go package main import ( - "math" + "image" + . "math" "gopkg.in/gographics/imagick.v2/imagick" ) @@ -19,14 +20,14 @@ func resizeImage(mw *imagick.MagickWand, newWidth, newHeight int, keepSpecSize, origHeight = int(mw.GetImageHeight()) origWidth = int(mw.GetImageWidth()) - //check if requested size is the same as current size + //check if requested size is the same as current size if (origHeight != newHeight) || (origWidth != newWidth) { - // width / height * newheight = newwidth + // width / height * newheight = newwidth if (round((float64(origWidth) / float64(origHeight)) * float64(newHeight))) <= newWidth { width = round((float64(origWidth) / float64(origHeight)) * float64(newHeight)) height = newHeight } else { - // height / width * newwidth = newheight + // height / width * newwidth = newheight height = round((float64(origHeight) / float64(origWidth)) * float64(newWidth)) width = newWidth } @@ -35,21 +36,21 @@ func resizeImage(mw *imagick.MagickWand, newWidth, newHeight int, keepSpecSize, width = newWidth } - //new magickwand for resized image + //new magickwand for resized image resmw = imagick.NewMagickWand() if !keepSpecSize { resmw.NewImage(uint(width), uint(height), imagick.NewPixelWand()) center = false } else { - //blank image + //blank image resmw.NewImage(uint(newWidth), uint(newHeight), imagick.NewPixelWand()) if center { err = mw.ResizeImage(uint(width), uint(height), imagick.FILTER_LANCZOS, 1) if err != nil { panic(err) } - //centers image + //centers image resmw.CompositeImage(mw, imagick.COMPOSITE_OP_SRC_OVER, round(float64(newWidth-width)/float64(2)), round(float64(newHeight-height)/float64(2))) } else { resmw.CompositeImage(mw, imagick.COMPOSITE_OP_SRC_OVER, 0, 0) @@ -60,9 +61,29 @@ func resizeImage(mw *imagick.MagickWand, newWidth, newHeight int, keepSpecSize, } +//getImage() from imagick to image.RGBA +func (cl cell) getImage(width, height int) (img *image.RGBA) { + mw := cl.img.GetImage() + if (width == 0) || (height == 0) { + width = int(mw.GetImageWidth()) + height = int(mw.GetImageHeight()) + } + + mw = resizeImage(mw, width, height, true, true) + img = image.NewRGBA(image.Rect(0, 0, int(width), int(height))) + if img.Stride != img.Rect.Size().X*4 { + panic("unsupported stride") + } + + Tpix, _ := mw.ExportImagePixels(0, 0, uint(width), uint(height), "RGBA", imagick.PIXEL_CHAR) + img.Pix = Tpix.([]uint8) + mw.Destroy() + return +} + func round(a float64) int { if a < 0 { - return int(math.Ceil(a - 0.5)) + return int(Ceil(a - 0.5)) } - return int(math.Floor(a + 0.5)) + return int(Floor(a + 0.5)) } diff --git a/imgprovider.go b/imgprovider.go deleted file mode 100644 index e518dbf..0000000 --- a/imgprovider.go +++ /dev/null @@ -1,23 +0,0 @@ -// imgprovider.go -package main - -import ( - "image" - "strconv" - "strings" -) - -var imgready = false - -func imgProvider(id string, width, height int) image.Image { - if imgready && (len(id) > 0) { - //fmt.Println("source (provider): ", id) - i1 := strings.Index(id, `;`) - i, _ := strconv.Atoi(id[:i1]) - return slides[i].getImage(width, height) - - } else { - var img1 image.Image = image.NewRGBA(image.Rect(0, 0, 340, 480)) - return img1 - } -} diff --git a/main.go b/main.go index 529c0e2..766cf5e 100644 --- a/main.go +++ b/main.go @@ -3,22 +3,15 @@ package main import ( "fmt" - "image" - "log" "os" "path/filepath" - "runtime/debug" - "strconv" - "strings" - "github.com/go-gl/gl/v2.1/gl" - "github.com/go-gl/glfw/v3.1/glfw" "github.com/kardianos/osext" "github.com/lordwelch/qml" "gopkg.in/gographics/imagick.v2/imagick" ) -//lazy wanted a toggle function +//Bool type i'm lazy wanted a toggle function type Bool bool type cell struct { @@ -31,24 +24,12 @@ type cell struct { type slide []*cell var ( - //displayed width/height the focused and the cell that was last right clicked - monWidth, monHeight, selCell, rhtClkCell int - path string - qimg qml.Object //file for the image object - textEdit qml.Object - cellQml qml.Object //file for the cell object - window *qml.Window //QML - win *glfw.Window //GLFW - slides slide - err error - monitors []*glfw.Monitor - projMonitor *glfw.Monitor - tex1 *uint32 //identifier for opengl texture - texDel, quickEdit Bool = false, false //if texture should be deleted + path string + slides slide + err error ) func main() { - selCell = 0 if err = qml.Run(run); err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) @@ -58,7 +39,6 @@ func main() { } func run() error { - var mainQml qml.Object imagick.Initialize() engine := qml.NewEngine() @@ -85,15 +65,15 @@ func run() error { window = mainQml.CreateWindow(nil) textEdit = window.ObjectByName("textEdit") - slides.addCell() - //signals for whole qml setSignals() + slides.add() //image is ready for imageprovider imgready = true window.Show() + slides[0].clearcache() qml.RunMain(glInit) window.Wait() @@ -102,290 +82,8 @@ func run() error { return nil } -func setupScene() { - - gl.ClearColor(0, 0, 0, 0) - if texDel { - gl.DeleteTextures(1, tex1) - } - tex1 = newTexture(*slides[selCell].getImage(monWidth, monHeight)) - - gl.MatrixMode(gl.PROJECTION) - gl.LoadIdentity() - gl.Ortho(-1, 1, -1, 1, 1.0, 10.0) - gl.MatrixMode(gl.MODELVIEW) - gl.LoadIdentity() - texDel = true - -} - -func drawSlide() { - gl.Clear(gl.COLOR_BUFFER_BIT) - - gl.MatrixMode(gl.MODELVIEW) - gl.LoadIdentity() - gl.Translatef(0, 0, -3.0) - - gl.Begin(gl.QUADS) - - //top left - gl.TexCoord2f(0, 0) - gl.Vertex3f(-1, 1, 0) - //top right - gl.TexCoord2f(1, 0) - gl.Vertex3f(1, 1, 0) - - //bottom right - gl.TexCoord2f(1, 1) - gl.Vertex3f(1, -1, 0) - - //bottom left - gl.TexCoord2f(0, 1) - gl.Vertex3f(-1, -1, 0) - - gl.End() - -} - -func newTexture(rgba image.RGBA) *uint32 { - var texture1 uint32 - gl.Enable(gl.TEXTURE_2D) - gl.GenTextures(1, &texture1) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) - gl.TexImage2D( - gl.TEXTURE_2D, - 0, - gl.RGBA, - int32(rgba.Rect.Size().X), - int32(rgba.Rect.Size().Y), - 0, - gl.RGBA, - gl.UNSIGNED_BYTE, - gl.Ptr(rgba.Pix)) - - return &texture1 - -} - -func checkMon() { - monitors = glfw.GetMonitors() - glfw.WindowHint(glfw.ContextVersionMajor, 2) - glfw.WindowHint(glfw.ContextVersionMinor, 1) - glfw.WindowHint(glfw.AutoIconify, glfw.False) - glfw.WindowHint(glfw.Decorated, glfw.False) - - if i := len(monitors); i < 2 { - fmt.Println("You only have 1 monitor!!!!!!!!!!! :-P") - monWidth = 800 - monHeight = 600 - - win, err = glfw.CreateWindow(monWidth, monHeight, "Cube", nil, nil) - if err != nil { - panic(err) - } - projMonitor = monitors[0] - } else { - fmt.Printf("You have %d monitors\n", i) - monWidth = monitors[1].GetVideoMode().Width - monHeight = monitors[1].GetVideoMode().Height - win, err = glfw.CreateWindow(monWidth, monHeight, "Cube", nil, nil) - fmt.Println(win.GetPos()) - win.SetPos(monitors[1].GetPos()) - fmt.Println(monWidth, monHeight) - if err != nil { - panic(err) - } - projMonitor = monitors[1] - - } - monitorInfo() - -} - -func monitorInfo() { - for _, mon := range monitors { - fmt.Printf("monitor name: %s\n", mon.GetName()) - i, t := mon.GetPos() - fmt.Printf("position X: %d Y: %d\n", i, t) - - } - -} - -func glInit() { - if err = glfw.Init(); err != nil { - log.Fatalln("failed to initialize glfw:", err) - } - checkMon() - - win.MakeContextCurrent() - - if err := gl.Init(); err != nil { - panic(err) - } - - win.SetPos(projMonitor.GetPos()) - setupScene() - - qml.Func1 = func() int { - if !win.ShouldClose() { - glfw.PollEvents() - drawSlide() - win.SwapBuffers() - return 0 - - } else { - win.Hide() - //win.Destroy() - glfw.Terminate() - return 1 - - } - } -} - -//setSignals() for non dynamic elements -func setSignals() { - window.ObjectByName("imgpicker").On("accepted", func() { - //delete file:// from url - url := filepath.Clean(strings.Replace(window.ObjectByName("imgpicker").String("fileUrl"), "file:", "", 1)) - - //replace new image - slides[rhtClkCell].img.Clear() - slides[rhtClkCell].img.ReadImage(url) - setupScene() - //update image preview - slides[rhtClkCell].clearcache() - }) - - window.ObjectByName("btnAdd").On("clicked", func() { - slides.addCell() - }) - - window.ObjectByName("btnRem").On("clicked", func() { - slides[len(slides)-1].remove() - }) - - window.ObjectByName("btnMem").On("clicked", func() { - //run GC - debug.FreeOSMemory() - }) - - window.On("closing", func() { - //close glfw first - if false == window.Property("cls") { - win.SetShouldClose(true) - window.Set("cls", true) - } - - }) - - window.ObjectByName("mnuEdit").On("triggered", func() { - (&quickEdit).Toggle() - }) - - textEdit.ObjectByName("textEdit1").On("focusChanged", func(focus bool) { - var ( - str string - cel *cell - ) - - if !focus { - //set text back to the cell - str = textEdit.ObjectByName("textEdit1").String("text") - cel = slides[textEdit.Int("cell")] - if textEdit.Bool("txt") { - cel.qmlcell.ObjectByName("cellText").Set("text", str) - cel.text = str - } - } - }) - -} - -//getImage() from imagick to image.RGBA -func (cl cell) getImage(width, height int) (img *image.RGBA) { - mw := cl.img.GetImage() - if (width == 0) || (height == 0) { - width = int(mw.GetImageWidth()) - height = int(mw.GetImageHeight()) - } - - mw = resizeImage(mw, width, height, true, true) - img = image.NewRGBA(image.Rect(0, 0, int(width), int(height))) - if img.Stride != img.Rect.Size().X*4 { - panic("unsupported stride") - } - - Tpix, _ := mw.ExportImagePixels(0, 0, uint(width), uint(height), "RGBA", imagick.PIXEL_CHAR) - img.Pix = Tpix.([]uint8) - mw.Destroy() - return -} - -//signals for the cell and image in qml -func (cl *cell) setSignal() { - cl.qmlcell.ObjectByName("cellMouse").On("clicked", func(musEvent qml.Object) { - btn := musEvent.Property("button") - //right click - if btn == 2 { - //context menu - window.ObjectByName("mnuCtx").Call("popup") - rhtClkCell = cl.index - } else { - //left click - //select and update image preview for cell - selCell = cl.qmlcell.Int("index") - cl.qmlcell.ObjectByName("cellMouse").Set("focus", true) - setupScene() - } - //update image preview - cl.clearcache() - }) - - cl.qmlcell.ObjectByName("cellMouse").On("focusChanged", func(focus bool) { - if focus { - cl.qmlcell.ObjectByName("cellMouse").Call("selected") - } else { - cl.qmlcell.ObjectByName("cellMouse").Call("notSelected") - } - }) - - cl.qmlcell.ObjectByName("cellMouse").On("doubleClicked", func() { - if quickEdit { - //cover the cell with the text edit - textEdit.Set("cell", cl.index) - textEdit.Set("x", cl.qmlcell.Int("x")) - textEdit.Set("y", cl.qmlcell.Int("y")) - textEdit.Set("height", cl.qmlcell.Int("height")) - textEdit.Set("z", 100) - textEdit.Set("visible", true) - textEdit.ObjectByName("textEdit1").Set("focus", true) - textEdit.Set("enabled", true) - - //set the text - textEdit.ObjectByName("textEdit1").Set("text", cl.text) - } - }) - -} - -//clear cache dosen't actually clear the cache -//just gives a new source so that the cache isn't used -func (cl *cell) clearcache() { - str := cl.qmlimg.String("source") - //fmt.Println("source (click): ", str) - i := strings.Index(str, `;`) - str1 := str[:i] - //fmt.Println("ext (click): ", str1) - i1, _ := strconv.Atoi(str[i+1:]) - str = str1 + `;` + strconv.Itoa(i1+1) - //fmt.Println("new source (click): ", str) - cl.qmlimg.Set("source", str) -} - //Adds a new cell -func (sl *slide) addCell( /*cl *cell*/ ) { +func (sl *slide) add( /*cl *cell*/ ) { var cl cell //gets the length so that the index is valid cl.index = len(*sl) @@ -411,17 +109,14 @@ func (sl *slide) addCell( /*cl *cell*/ ) { //seperate image object in QML cl.qmlimg = qimg.Create(nil) - fmt.Println("index", cl.index) - fmt.Printf("objectName: %s\n", fmt.Sprintf("cellImg%d", cl.index)) cl.qmlimg.Set("objectName", fmt.Sprintf("cellImg%d", cl.index)) cl.qmlimg.Set("source", fmt.Sprintf("image://images/%d"+`;`+"0", cl.index)) - fmt.Println("source: ", cl.qmlimg.String("source")) cl.qmlimg.Set("parent", window.ObjectByName("data2")) cl.qmlimg.Set("index", cl.index) } -//remove() should destroy everything +//(cell) remove() should destroy everything func (cl *cell) remove() { cl.text = "" cl.qmlimg.Destroy() @@ -433,12 +128,12 @@ func (cl *cell) remove() { } -//(slide) remove copied from gist on github +//(slide) remove copied from github.com/golang/go/wiki/SliceTricks func (sl *slide) remove(i int) { *sl, (*sl)[len((*sl))-1] = append((*sl)[:i], (*sl)[i+1:]...), nil } -//lazy wanted a toggle func +//Toggle lazy wanted a func for it func (bl *Bool) Toggle() { if *bl == false { *bl = true diff --git a/main.qml b/main.qml index 80330e2..e6b5076 100644 --- a/main.qml +++ b/main.qml @@ -56,6 +56,15 @@ ApplicationWindow { } } + Menu { + title: "Window" + + MenuItem { + text: "Display" + objectName: "mnuDisplay" + } + } + Menu { title: "&Help" MenuItem { diff --git a/qml.go b/qml.go new file mode 100644 index 0000000..c0bf74f --- /dev/null +++ b/qml.go @@ -0,0 +1,162 @@ +// PresentationApp project qml.go +package main + +import ( + "image" + "path/filepath" + "runtime/debug" + "strconv" + "strings" + + "github.com/lordwelch/qml" +) + +var ( + selCell int //the focused and + rhtClkCell int //the cell that was last right clicked + qimg qml.Object //file for the image object + cellQml qml.Object //file for the cell object + mainQml qml.Object //main QML file + textEdit qml.Object + window *qml.Window + quickEdit Bool = false + imgready Bool = false +) + +//signals for the cell and image in qml +func (cl *cell) setSignal() { + cl.qmlcell.ObjectByName("cellMouse").On("clicked", func(musEvent qml.Object) { + btn := musEvent.Property("button") + //right click + if btn == 2 { + //context menu + window.ObjectByName("mnuCtx").Call("popup") + rhtClkCell = cl.index + } else { + //left click + //select and update image preview for cell + selCell = cl.qmlcell.Int("index") + cl.qmlcell.ObjectByName("cellMouse").Set("focus", true) + setupScene() + } + //update image preview + cl.clearcache() + }) + + cl.qmlcell.ObjectByName("cellMouse").On("focusChanged", func(focus bool) { + if focus { + cl.qmlcell.ObjectByName("cellMouse").Call("selected") + } else { + cl.qmlcell.ObjectByName("cellMouse").Call("notSelected") + } + }) + + cl.qmlcell.ObjectByName("cellMouse").On("doubleClicked", func() { + if quickEdit { + //cover the cell with the text edit + textEdit.Set("cell", cl.index) + textEdit.Set("x", cl.qmlcell.Int("x")) + textEdit.Set("y", cl.qmlcell.Int("y")) + textEdit.Set("height", cl.qmlcell.Int("height")) + textEdit.Set("z", 100) + textEdit.Set("visible", true) + textEdit.ObjectByName("textEdit1").Set("focus", true) + textEdit.Set("enabled", true) + + //set the text + textEdit.ObjectByName("textEdit1").Set("text", cl.text) + } + }) + +} + +//setSignals() for non dynamic elements +func setSignals() { + window.ObjectByName("imgpicker").On("accepted", func() { + //delete file:// from url + url := filepath.Clean(strings.Replace(window.ObjectByName("imgpicker").String("fileUrl"), "file:", "", 1)) + + //replace new image + slides[rhtClkCell].img.Clear() + slides[rhtClkCell].img.ReadImage(url) + setupScene() + //update image preview + slides[rhtClkCell].clearcache() + }) + + window.ObjectByName("btnAdd").On("clicked", func() { + slides.add() + }) + + window.ObjectByName("btnRem").On("clicked", func() { + slides[len(slides)-1].remove() + }) + + window.ObjectByName("btnMem").On("clicked", func() { + //run GC + debug.FreeOSMemory() + }) + + window.On("closing", func() { + //close glfw first + if false == window.Property("cls") { + win.SetShouldClose(true) + window.Set("cls", true) + } + + }) + + window.ObjectByName("mnuDisplay").On("triggered", func() { + qml.RunMain(glInit) + }) + + window.ObjectByName("mnuEdit").On("triggered", func() { + (&quickEdit).Toggle() + }) + + textEdit.ObjectByName("textEdit1").On("focusChanged", func(focus bool) { + var ( + str string + cel *cell + ) + + if !focus { + //set text back to the cell + str = textEdit.ObjectByName("textEdit1").String("text") + cel = slides[textEdit.Int("cell")] + if textEdit.Bool("txt") { + cel.qmlcell.ObjectByName("cellText").Set("text", str) + cel.text = str + } + } + }) + +} + +//imgProvider() for preview images in QML +func imgProvider(id string, width, height int) image.Image { + if imgready && (len(id) > 0) { + //fmt.Println("source (provider): ", id) + i1 := strings.Index(id, `;`) + i, _ := strconv.Atoi(id[:i1]) + return slides[i].getImage(width, height) + + } + var img1 image.Image = image.NewRGBA(image.Rect(0, 0, 340, 480)) + return img1 + +} + +//clear cache dosen't actually clear the cache +//just gives a new source so that the cache isn't used +func (cl *cell) clearcache() { + str := cl.qmlimg.String("source") + //fmt.Println("source (click): ", str) + i := strings.Index(str, `;`) + str1 := str[:i] + //fmt.Println("ext (click): ", str1) + i1, _ := strconv.Atoi(str[i+1:]) + str = str1 + `;` + strconv.Itoa(i1+1) + //fmt.Println("new source (click): ", str) + cl.qmlimg.Set("source", str) +} diff --git a/xml.go b/xml.go index 6700da7..b6938b0 100644 --- a/xml.go +++ b/xml.go @@ -1,3 +1,4 @@ +// PresentationApp project xml.go package main type _ struct {