Compare commits

..

No commits in common. "43d53879ba71f45f98b08dff5542ad64704e120f" and "7fe593a4ef3988ee088380284739be684b68d826" have entirely different histories.

19 changed files with 1015 additions and 814 deletions

1
.gitignore vendored
View File

@ -2,7 +2,6 @@
*.o *.o
*.a *.a
*.so *.so
PresentationApp
# Folders # Folders
_obj _obj

View File

@ -1,242 +0,0 @@
package main
import (
"os"
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/quick"
"github.com/therecipe/qt/widgets"
)
func init() {
CustomTreeModel_QmlRegisterType2("CustomQmlTypes", 1, 0, "CustomTreeModel")
}
const something = 1<<31 - 1
const (
FirstName = int(core.Qt__UserRole) + 1<<iota
LastName
)
type Collection struct {
title string
_childItems []CollectionItem
}
type CollectionItem struct {
_itemData []string
}
type ROOT []Collection
func (r *ROOT) add(t Collection) {
*r = append(*r, t)
}
func (r *ROOT) Len() int {
return len(*r)
}
func (r *ROOT) CollectionLen(i int) int {
return len((*r)[i]._childItems)
}
func (r *ROOT) Collection(index int) Collection {
return (*r)[index]
}
func (r *ROOT) CollectionItem(index int, Cindex int) CollectionItem {
return (*r)[index]._childItems[Cindex]
}
func NewCollectionItem(data []string) CollectionItem {
return CollectionItem{
_itemData: data,
}
}
type service interface {
add(t Collection)
Len() int
Collection(index int) Collection
CollectionLen(i int) int
CollectionItem(index int, listIndex int) CollectionItem
}
type CustomTreeModel struct {
core.QAbstractItemModel
_ func() `constructor:"init"`
// _ func() `signal:"remove,auto"`
// _ func(item []*core.QVariant) `signal:"add,auto"`
// _ func(firstName string, lastName string) `signal:"edit,auto"`
rootItem service // ROOT
}
func (m *CustomTreeModel) init() {
m.rootItem = &ROOT{
Collection{
title: "FirstName LastName",
_childItems: []CollectionItem{
CollectionItem{
_itemData: []string{"john", "doe"},
},
},
},
}
m.rootItem.add(Collection{
title: "FirstName LastName2",
_childItems: []CollectionItem{
CollectionItem{
_itemData: []string{"john", "bob"},
},
CollectionItem{
_itemData: []string{"jim", "bob"},
},
CollectionItem{
_itemData: []string{"jimmy", "bob"},
},
},
})
m.ConnectIndex(m.index)
m.ConnectParent(m.parent)
m.ConnectRowCount(m.rowCount)
m.ConnectColumnCount(m.columnCount)
m.ConnectData(m.data)
m.ConnectRoleNames(m.roleNames)
}
func (m *CustomTreeModel) index(row int, column int, parent *core.QModelIndex) *core.QModelIndex {
if !m.HasIndex(row, column, parent) {
return core.NewQModelIndex()
}
if !parent.IsValid() {
return m.CreateIndex2(row, column, something)
} else {
return m.CreateIndex2(row, column, uintptr(parent.Row()))
}
return core.NewQModelIndex()
}
func (m *CustomTreeModel) parent(index *core.QModelIndex) *core.QModelIndex {
if !index.IsValid() {
return core.NewQModelIndex()
}
id := int(index.InternalId())
if id == something {
return core.NewQModelIndex()
}
return m.CreateIndex2(id, 0, something)
}
func (m *CustomTreeModel) roleNames() map[int]*core.QByteArray {
return map[int]*core.QByteArray{
FirstName: core.NewQByteArray2("FirstName", -1),
LastName: core.NewQByteArray2("LastName", -1),
}
}
func (m *CustomTreeModel) rowCount(parent *core.QModelIndex) int {
if !parent.IsValid() {
return m.rootItem.Len()
}
parentId := int32(parent.InternalId())
if parentId == something {
return m.rootItem.CollectionLen(parent.Row())
}
return 0
}
func (m *CustomTreeModel) columnCount(parent *core.QModelIndex) int {
if !parent.IsValid() {
return 1
}
parentId := int32(parent.InternalId())
if parentId == something {
return 1 //len(r[parent.Row()].title)
}
return 0
}
func (m *CustomTreeModel) data(index *core.QModelIndex, role int) *core.QVariant {
if !index.IsValid() {
return core.NewQVariant()
}
if int32(index.InternalId()) == something {
return core.NewQVariant17(m.rootItem.Collection(index.Row()).title)
}
switch role {
case FirstName:
return core.NewQVariant17(m.rootItem.CollectionItem(int(index.InternalId()), index.Row())._itemData[0])
case LastName:
return core.NewQVariant17(m.rootItem.CollectionItem(int(index.InternalId()), index.Row())._itemData[1])
}
return core.NewQVariant()
}
// func (m *CustomTreeModel) remove() {
// if m.rootItem.childCount() == 0 {
// return
// }
// m.BeginRemoveRows(core.NewQModelIndex(), len(m.rootItem._childItems)-1, len(m.rootItem._childItems)-1)
// m.rootItem._childItems = m.rootItem._childItems[:len(m.rootItem._childItems)-1]
// m.EndRemoveRows()
// }
// func (m *CustomTreeModel) add(item []*core.QVariant) {
// m.BeginInsertRows(core.NewQModelIndex(), len(m.rootItem._childItems), len(m.rootItem._childItems))
// m.rootItem.appendChild(NewTreeItem([]string{item[0].ToString(), item[1].ToString()}))
// m.EndInsertRows()
// }
// func (m *CustomTreeModel) edit(firstName string, lastName string) {
// if m.rootItem.childCount() == 0 {
// return
// }
// m.BeginRemoveRows(core.NewQModelIndex(), len(m.rootItem._childItems)-1, len(m.rootItem._childItems)-1)
// m.BeginInsertRows(core.NewQModelIndex(), len(m.rootItem._childItems)-1, len(m.rootItem._childItems)-1)
// item := m.rootItem._childItems[len(m.rootItem._childItems)-1]
// item._itemData = []string{firstName, lastName}
// m.EndRemoveRows()
// m.EndInsertRows()
// //TODO:
// //ideally DataChanged should be used instead, but it doesn't seem to work ...
// //if you search for "qml treeview datachanged" online
// //it will just lead you to tons of unresolved issues
// //m.DataChanged(m.Index(item.row(), 0, core.NewQModelIndex()), m.Index(item.row(), 1, core.NewQModelIndex()), []int{FirstName, LastName})
// //feel free to send a PR, if you got it working somehow :)
// }
func main() {
core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)
if !core.QResource_RegisterResource("qml.rcc", "") {
panic("failure: resource needed")
}
// gui.QGuiApplication_Screens()[0].
app := widgets.NewQApplication(len(os.Args), os.Args)
view := quick.NewQQuickView(nil)
view.SetTitle("treeview Example")
view.SetResizeMode(quick.QQuickView__SizeRootObjectToView)
view.SetSource(core.NewQUrl3("qrc:/qml/main.qml", 0))
// view.SetPosition2(posx, posy)
view.ShowMaximized()
app.Exec()
}

163
glfw.go Normal file
View File

@ -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
}
}

View File

@ -1,61 +0,0 @@
// PresentationApp project imagick.go
package main
import (
"image"
"io/ioutil"
"path/filepath"
"strings"
"github.com/disintegration/imaging"
"github.com/flopp/go-findfont"
"github.com/fogleman/gg"
)
/*resizeImage() src fullsize image
newWidth, newHeight = size to be resized to
keepSpecSize = return image with exactly the size specified or just the size of the resized image
center = center the image
*/
func resizeImage(src image.Image, newWidth, newHeight int, keepSpecSize, center bool) (dst image.Image) {
imaging.Fit(src, newWidth, newHeight, imaging.Lanczos)
if keepSpecSize {
//blank image
dst = image.NewNRGBA(image.Rect(0, 0, newWidth, newHeight))
if center {
dst = imaging.OverlayCenter(dst, src, 1)
} else {
dst = imaging.Overlay(dst, src, image.Pt(0, 0), 1)
}
}
return dst
}
// adding text to image copied from example
func (cl *Cell) imgtext(width, height int) image.Image {
ctx := gg.NewContextForImage(cl.image.resized)
ctx.SetColor(cl.Font.color)
if (cl.Font.name != "") || (cl.Font.name != "none") {
data, err := ioutil.ReadFile(cl.Font.name)
if err != nil {
return image.Rectangle{}
}
if err := ctx.LoadFontData(data, cl.Font.size); err != nil {
panic(err)
}
}
ctx.DrawStringWrapped(cl.text, 0, 0, 0, 0, float64(width), 1, gg.AlignCenter)
return ctx.Image()
}
func findFonts() {
paths := findfont.List()
for i, v := range paths {
_, paths[i] = filepath.Split(v)
}
QML.FontList = strings.Join(paths, "\n")
}

172
imagick.go Normal file
View File

@ -0,0 +1,172 @@
// PresentationApp project imagick.go
package main
import (
"bytes"
"fmt"
"image"
"log"
"math"
"os/exec"
"strings"
"gopkg.in/gographics/imagick.v2/imagick"
)
/*resizeImage() mw fullsize image
newwidth, newheight = size to be resized to
keepSpecSize = return image with exactly the size specified or just the size of the resized image
center = senter the image
*/
func resizeImage(mw *imagick.MagickWand, newWidth, newHeight int, keepSpecSize, center bool) (resmw *imagick.MagickWand) {
var (
width, height, origHeight, origWidth int
)
origHeight = int(mw.GetImageHeight())
origWidth = int(mw.GetImageWidth())
//check if requested size is the same as current size
if (origHeight != newHeight) || (origWidth != 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 = round((float64(origHeight) / float64(origWidth)) * float64(newWidth))
width = newWidth
}
} else {
height = newHeight
width = newWidth
}
//new magickwand for resized image
resmw = imagick.NewMagickWand()
if !keepSpecSize {
resmw.NewImage(uint(width), uint(height), imagick.NewPixelWand())
center = false
} else {
//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
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)
}
}
mw.Destroy()
return resmw
}
//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)
mw1 := cl.imgtext(width, height)
mw.CompositeImage(mw1, imagick.COMPOSITE_OP_OVER, 0, 0)
mw1.Destroy()
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
}
// adding text to image copied from example
func (cl *cell) imgtext(width, height int) *imagick.MagickWand {
mw := imagick.NewMagickWand()
//defer mw.Destroy()
dw := imagick.NewDrawingWand()
defer dw.Destroy()
pw := imagick.NewPixelWand()
defer pw.Destroy()
pw.SetColor("none")
// Create a new transparent image
mw.NewImage(uint(width), uint(height), pw)
// Set up a 72 point white font
r, g, b, _ := cl.font.color.RGBA()
pw.SetColor(fmt.Sprintf("rgb(%d,%d,%d)", r, g, b))
dw.SetFillColor(pw)
if (cl.font.name != "") || (cl.font.name != "none") {
dw.SetFont(cl.font.name)
}
dw.SetFontSize(cl.font.size)
otlne := "none"
// Add a black outline to the text
r, g, b, _ = cl.font.outlineColor.RGBA()
if cl.font.outline {
otlne = fmt.Sprintf("rgb(%d,%d,%d)", r, g, b)
}
pw.SetColor(otlne)
dw.SetStrokeColor(pw)
dw.SetStrokeWidth(cl.font.outlineSize)
// Turn antialias on - not sure this makes a difference
//dw.SetTextAntialias(true)
// Now draw the text
dw.Annotation(cl.font.x, cl.font.y, cl.text)
// Draw the image on to the mw
mw.DrawImage(dw)
// equivalent to the command line +repage
mw.ResetImagePage("")
// Make a copy of the text image
cw := mw.Clone()
// Set the background colour to blue for the shadow
pw.SetColor("black")
mw.SetImageBackgroundColor(pw)
// Opacity is a real number indicating (apparently) percentage
mw.ShadowImage(70, 4, 5, 5)
// Composite the text on top of the shadow
mw.CompositeImage(cw, imagick.COMPOSITE_OP_OVER, 5, 5)
cw.Destroy()
return mw
}
func findfonts() {
cmd := exec.Command("grep", "-ivE", `\-Oblique$|-Bold$|-Italic$|-Light$`)
cmd.Stdin = strings.NewReader(strings.Join(imagick.QueryFonts("*"), "\n"))
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
log.Print(err)
}
QML.FontList = strings.Split(out.String(), "\n")
QML.FontLen = len(QML.FontList)
}
func round(a float64) int {
if a < 0 {
return int(math.Ceil(a - 0.5))
}
return int(math.Floor(a + 0.5))
}

274
main.go
View File

@ -1,208 +1,198 @@
// PresentationApp project main.go // PresentationApp project main.go
//go:generate genqrc qml
package main package main
import ( import (
"fmt" "fmt"
"image"
"image/color" "image/color"
"os" "os"
"path/filepath"
"github.com/go-gl/glfw/v3.1/glfw" "github.com/go-gl/glfw/v3.1/glfw"
"github.com/limetext/qml-go" "github.com/kardianos/osext"
"github.com/lordwelch/qml"
"gopkg.in/gographics/imagick.v2/imagick"
) )
type Cell struct { //Bool type i'm lazy wanted a toggle function
Font Font type Bool bool
image Image
index, collectionIndex int
text string
textVisible bool
}
type collection struct {
collection []*Cell
title string
}
type Font struct {
color color.RGBA
name string
path string
outline bool
outlineColor color.RGBA
outlineSize, size, x, y float64
}
type Image struct {
path string
original image.Image
resized image.Image
}
type qmlVar struct { type qmlVar struct {
FontList string FontList []string
Verses string FontLen int
VerseOrder string Verses []string
VerseLen int
VerseOrder []string
OrderLen int
Img []string
ImgLen int
} }
type service []collection type cell struct {
text string
img *imagick.MagickWand
qmlimg qml.Object
qmlcell qml.Object
index int
font struct {
name string
outlineSize, size, x, y float64
color color.RGBA
outlineColor color.RGBA
outline Bool
}
}
type slide []*cell
var ( var (
currentService = new(service) path string
err error slides slide
path string err error
slides collection
) )
func main() { func main() {
if err = qml.Run(run); err != nil { if err = qml.Run(run); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err) fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1) os.Exit(1)
} }
win.Destroy()
glfw.PollEvents()
glfw.Terminate() glfw.Terminate()
} }
func run() error { func run() error {
imagick.Initialize()
engine = qml.NewEngine() engine = qml.NewEngine()
QML = &qmlVar{} QML = &qmlVar{}
path = "qrc:///qml"
findFonts()
engine.Context().SetVar("go", QML) engine.Context().SetVar("go", QML)
findfonts()
engine.AddImageProvider("images", imgProvider) engine.AddImageProvider("images", imgProvider)
//path for qml files TODO: change to somewhere else
path, err = osext.ExecutableFolder()
path = filepath.Clean(path + "/../src/github.com/lordwelch/PresentationApp/")
err = qmlWindows() mainQml, err = engine.LoadFile(path + "/main.qml")
if err != nil { if err != nil {
return err return err
} }
currentService.Init(1) edtQml, err = engine.LoadFile(path + "/qml/songEdit.qml")
if err != nil {
return err
}
cellQml, err = engine.LoadFile(path + "/qml/cell.qml")
if err != nil {
return err
}
qimg, err = engine.LoadFile(path + "/qml/img.qml")
if err != nil {
return err
}
window = mainQml.CreateWindow(engine.Context())
window2 = edtQml.CreateWindow(engine.Context())
textEdit = window.ObjectByName("textEdit")
//signals for whole qml
setSignals()
slides.add()
//var from GO to qml
//image is ready for imageprovider //image is ready for imageprovider
imgready = true imgready = true
displayImg = DisplayWindow.Root().ObjectByName("displayImage") window.Show()
serviceObject = serviceQml.Create(engine.Context()) window2.Show()
serviceObject.Set("parent", MainWindow.ObjectByName("scview")) edtQmlShow()
serviceObject.Call("addLst", "not") slides[0].clearcache()
//edtQmlShow()
qml.RunMain(glInit) qml.RunMain(glInit)
MainWindow.Wait()
slides.destroy()
fmt.Println(len(*currentService))
window.Wait()
imagick.Terminate()
return nil return nil
} }
func (sv *service) Init(num int) {
if num <= 0 {
num = 1
}
for index := 0; index < num; index++ {
if sv == nil {
sv.add("")
}
}
}
func (sv *service) add(name string) {
var (
sl collection
i = len(*sv)
)
if len(name) <= 0 {
name = "Song: " + fmt.Sprint(i)
}
sl.init(1)
*sv = append(*sv, sl)
//serviceObject.Call("addLst", name)
}
func (sv *service) remove(i int) {
(*sv)[i].destroy()
copy((*sv)[i:], (*sv)[i+1:])
(*sv)[len(*sv)-1] = nil // or the zero value of T
*sv = (*sv)[:len(*sv)-1]
}
func (sv *service) destroy() {
for i := len(*sv); i > 0; i-- {
sv.remove(i - 1)
}
}
func (sl *collection) init(num int) {
if num <= 0 {
num = 1
}
for index := 0; index < num; index++ {
if sl == nil {
sl.add("")
}
}
}
//Adds a new cell //Adds a new cell
func (sl *collection) add(text string) { func (sl *slide) add( /*cl *cell*/ ) {
var ( var cl cell
cl Cell
i = len(*sl)
)
if len(text) <= 0 {
text = "Slide" + fmt.Sprint(i)
}
cl.Init() cl.Init()
//gets the length so that the index is valid
cl.index = len(*sl)
//increase count on parent QML element
window.ObjectByName("gridRect").Set("count", window.ObjectByName("gridRect").Int("count")+1)
cl.qmlcell = cellQml.Create(engine.Context())
cl.qmlcell.Set("objectName", fmt.Sprintf("cellRect%d", len(*sl)))
cl.qmlcell.Set("parent", window.ObjectByName("data1"))
cl.qmlcell.Set("index", cl.index)
//keep the pointer/dereference (i'm not sure which it is) //keep the pointer/dereference (i'm not sure which it is)
//problems occur otherwise //problems occur otherwise
// now Im not an idiot and I know what this does
*sl = append(*sl, &cl) *sl = append(*sl, &cl)
//seperate image object in QML
cl.qmlimg.Set("objectName", fmt.Sprintf("cellImg%d", cl.index))
cl.qmlimg.Set("source", fmt.Sprintf("image://images/%d"+`;`+"0", cl.index))
cl.qmlimg.Set("parent", window.ObjectByName("data2"))
cl.qmlimg.Set("index", cl.index)
cl.setSignal()
//give QML the text
cl.qmlcell.ObjectByName("cellText").Set("text", cl.text)
} }
// remove copied from github.com/golang/go/wiki/SliceTricks func (cl *cell) Init() {
func (sl *collection) remove(i int) { cl.text = "hello this is text\nhaha\nhdsjfklfhaskjd"
cl := (*sl)[i] cl.index = -1
cl.font.color, cl.font.outlineColor = color.RGBA{0, 0, 0, 1}, color.RGBA{1, 1, 1, 1}
cl.font.name = "none"
cl.font.outline = false
cl.font.outlineSize = 1
cl.font.size = 35
cl.font.x, cl.font.y = 10, 30
cl.qmlcell = cellQml.Create(engine.Context())
cl.qmlimg = qimg.Create(engine.Context())
//load image
cl.img = imagick.NewMagickWand()
cl.img.ReadImage("logo:")
}
//(cell) remove() should destroy everything for this cell
func (cl *cell) remove() {
cl.text = "" cl.text = ""
MainWindow.ObjectByName("gridRect").Set("count", MainWindow.ObjectByName("gridRect").Int("count")-1) cl.qmlimg.Destroy()
cl.qmlcell.Destroy()
cl.img.Destroy()
window.ObjectByName("gridRect").Set("count", window.ObjectByName("gridRect").Int("count")-1)
slides.remove(cl.index)
cl.index = -1 cl.index = -1
copy((*sl)[i:], (*sl)[i+1:])
(*sl)[len(*sl)-1] = nil // or the zero value of T
(*sl) = (*sl)[:len(*sl)-1]
//*sl, (*sl)[len((*sl))-1] = append((*sl)[:i], (*sl)[i+1:]...), nil
} }
func (sl *collection) destroy() { //(slide) remove copied from github.com/golang/go/wiki/SliceTricks
for i := len(*sl); i > 0; i-- { func (sl *slide) remove(i int) {
sl.remove(i - 1) *sl, (*sl)[len((*sl))-1] = append((*sl)[:i], (*sl)[i+1:]...), nil
}
//Toggle, lazy wanted a func for it
func (bl *Bool) Toggle() {
if *bl == false {
*bl = true
} else {
*bl = false
} }
} }
func (cl *Cell) Init() {
cl.text = `hello this is text`
cl.index = -1
cl.Font.color, cl.Font.outlineColor = color.RGBA{0, 0, 0, 1}, color.RGBA{1, 1, 1, 1}
cl.Font.name = "none"
cl.Font.outline = false
cl.Font.outlineSize = 1
cl.Font.size = 35
cl.Font.x, cl.Font.y = 10, 30
}
//not really needed //not really needed
func (cl Cell) String() string { func (cl cell) String() string {
return fmt.Sprintf("Index: %d \nText: %s\n", cl.index, cl.text) return fmt.Sprintf("Index: %d \nText: %s\n", cl.index, cl.text)
} }

253
main.qml Normal file
View File

@ -0,0 +1,253 @@
import QtQuick 2.4
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.3
import QtQuick.Window 2.0
import "qml"
import QtQuick.Layouts 1.0
ApplicationWindow {
id: applicationWindow1
title: "Presentation App"
visible: true
objectName: "applicationWindow1"
minimumWidth: 500
minimumHeight: 500
width: 1000
height: 600
property bool cls: false
/*function getFileDialogUrl() {
return
}*/
onClosing: if (!cls) {
close.accepted = false
}
FileDialog {
id: imgpicker
// @disable-check M16
title: "Choose an image for this slide"
// @disable-check M16
objectName: "imgpicker"
}
AboutDialog {
id: aboutDialog
}
Action {
id: aboutAction
text: "About"
onTriggered: aboutDialog.open()
}
menuBar: MenuBar {
Menu {
title: "&File"
MenuItem {
text: "Close"
shortcut: StandardKey.Quit
}
}
Menu {
title: "&Edit"
MenuItem {
text: "quick edit"
objectName: "mnuEdit"
}
}
Menu {
title: "Window"
MenuItem {
text: "Display"
objectName: "mnuDisplay"
}
}
Menu {
title: "&Help"
MenuItem {
action: aboutAction
}
}
}
Menu {
objectName: "mnuCtx"
title: "new image..."
MenuItem {
objectName: "mnuImgPick"
text: "new Image..."
onTriggered: imgpicker.open()
}
}
SplitView {
id: mainSlider
objectName: "mainSlider"
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
anchors.left: parent.left
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0
orientation: Qt.Horizontal
onResizingChanged: col1.width = gridData.width / 2
Rectangle {
id: gridRect
objectName: "gridRect"
width: 300
color: "#00000000"
border.width: 4
anchors.left: parent.left
anchors.leftMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.topMargin: 0
property int count: 0
ScrollView {
id: scview
anchors.fill: parent
anchors.margins: 4
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn
SplitView {
id: gridData
objectName: "gridData"
width: scview.width - 1
height: gridRect.count * 101
Rectangle {
id: col1
objectName: "col1"
width: gridData.width / 2
color: "#00000000"
transformOrigin: Item.TopLeft
border.width: 0
Rectangle {
id: textEdit
property int cell
x: 232
y: 622
objectName: "textEdit"
width: 200
height: 200
color: "#ffffff"
visible: false
property bool txt: true
Keys.onPressed: {
if ((event.key == Qt.Key_Return)
&& (event.modifiers & Qt.ControlModifier)) {
txt = true
x = -100
y = -100
visible = false
focus = true
enabled = false
opacity = 0
textEdit1.focus = false
event.accepted = true
}
if (event.key == Qt.Key_Escape) {
txt = false
x = -100
y = -100
visible = false
focus = true
enabled = false
opacity = 0
textEdit1.focus = false
event.accepted = true
}
}
TextArea {
id: textEdit1
objectName: "textEdit1"
anchors.fill: parent
clip: true
textFormat: Text.AutoText
visible: true
font.pixelSize: 12
z: 99
}
}
Column {
id: data1
objectName: "data1"
spacing: 1
anchors.fill: parent
}
}
Rectangle {
id: col2
objectName: "col2"
color: "#00000000"
border.width: 0
Column {
id: data2
spacing: 1
objectName: "data2"
anchors.fill: parent
}
}
}
}
}
Rectangle {
id: mainView
border.width: 0
objectName: "mainView"
anchors.right: parent.right
anchors.rightMargin: 0
anchors.leftMargin: 0
anchors.left: gridRect.right
anchors.bottom: parent.bottom
anchors.top: parent.top
z: 1
clip: false
visible: true
Button {
id: button1
objectName: "btnAdd"
x: 8
y: 8
text: qsTr("Button")
}
Button {
id: button2
x: 8
y: 39
text: qsTr("Button")
objectName: "btnRem"
}
Button {
id: button3
x: 8
y: 70
text: qsTr("Button")
objectName: "btnMem"
}
}
}
}

195
qml.go
View File

@ -2,20 +2,203 @@
package main package main
import ( import (
"fmt"
"image" "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
edtQml qml.Object
textEdit qml.Object
window *qml.Window
window2 *qml.Window
engine *qml.Engine
quickEdit Bool = false
imgready Bool = false
QML *qmlVar
)
func initQML() {
window2.ObjectByName("textClrDialog").On("accepted", func() {
window2.ObjectByName("textClrDialog").Color("color")
})
}
func (qv *qmlVar) Changed() {
qml.Changed(qv, qv.VerseLen)
qml.Changed(qv, qv.OrderLen)
qml.Changed(qv, qv.ImgLen)
qml.Changed(qv, qv.FontLen)
}
//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.qmlimg.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() {
win.SetShouldClose(false)
window.Set("cls", false)
win.Show()
qml.ResetGLFW()
})
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
}
}
})
}
func edtQmlShow() {
slc := window2.ObjectByName("fontPicker").Property("model")
fmt.Println(slc)
}
//imgProvider() for preview images in QML //imgProvider() for preview images in QML
func imgProvider(id string, width, height int) image.Image { func imgProvider(id string, width, height int) image.Image {
var img1 image.Image
if imgready && (len(id) > 0) { if imgready && (len(id) > 0) {
//fmt.Println("source (provider): ", id) //fmt.Println("source (provider): ", id)
// i1 := strings.Index(id, `;`) i1 := strings.Index(id, `;`)
// i, _ := strconv.Atoi(id[:i1]) i, _ := strconv.Atoi(id[:i1])
// img1 = slides[i].getImage(width, height) return slides[i].getImage(width, height)
} else {
img1 = image.NewRGBA(image.Rect(0, 0, 340, 480))
} }
var img1 image.Image = image.NewRGBA(image.Rect(0, 0, 340, 480))
return img1 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)
}

12
qml/AboutDialog.qml Normal file
View File

@ -0,0 +1,12 @@
import QtQuick 2.4
import QtQuick.Dialogs 1.1
MessageDialog {
icon: StandardIcon.Information
text: "Presentation App \nVersion: Alpha"
detailedText: "Presentation App for use in a church service\nMade in 2016 by Timmy Welch."
title: "About"
height: 100
width: 200
standardButtons: StandardButton.Close
}

View File

@ -1,37 +0,0 @@
import QtQuick 2.4
import QtQuick.Layouts 1.11
Rectangle {
id: itm
height: 100
anchors.right: parent.right
anchors.left: parent.left
property alias text: cellText.text
Rectangle {
id: half1
height: 100
Layout.fillWidth: true
Layout.minimumWidth: 100
Rectangle {
objectName: "cellRect"
property int index: 0
anchors.fill: parent
border.width: 2
border.color: "black"
Text {
id: cellText
enabled: true
objectName: "cellText"
// text: "itm.model.text"
renderType: Text.NativeRendering
clip: true
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
anchors.fill: parent
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 2
}
}
}
}

View File

@ -1,21 +0,0 @@
import QtQuick 2.4
import QtQuick.Controls 2.4
ApplicationWindow {
flags: Qt.MaximumSize
Component.onCompleted: visible = true
Image {
id: image1
objectName: "displayImage"
sourceSize.height: 768
sourceSize.width: 1024
antialiasing: true
anchors.fill: parent
}
}
/*##^## Designer {
D{i:0;autoSize:true;height:480;width:640}
}
##^##*/

View File

@ -1,159 +0,0 @@
import QtQuick 2.4
import QtQuick.Controls 1.6 as Quick
import QtQuick.Controls 2.4
import QtQuick.Dialogs 1.3
import QtQuick.Window 2.11
import QtQuick.Layouts 1.11
ApplicationWindow {
id: applicationWindow1
title: "Presentation App"
visible: true
objectName: "applicationWindow1"
minimumWidth: 500
minimumHeight: 500
FileDialog {
id: imgpicker
objectName: "imgpicker"
title: "Choose an image for this slide"
}
Quick.SplitView {
id: spview
anchors.fill: parent
Rectangle {
id: preview
objectName: "col1"
border.width: 0
Layout.minimumWidth: 150
Layout.fillWidth: true
Flickable {
id: scview
objectName: "scview"
anchors.fill: parent
boundsBehavior: Flickable.OvershootBounds
flickableDirection: Flickable.VerticalFlick
pixelAligned: true
//verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn
//horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
//highlightOnFocus: false
//frameVisible: true
contentHeight: contentItem.childrenRect.height
Quick.SplitView {
anchors.fill: parent
}
Rectangle {
id: textEdit
objectName: "textEdit"
visible: false
property bool keepText: true
Keys.onPressed: {
if ((event.key == Qt.Key_Return)
&& (event.modifiers & Qt.ControlModifier)) {
keepText = true
textEdit1.focus = false
event.accepted = true
}
if (event.key == Qt.Key_Escape) {
keepText = false
textEdit1.focus = false
event.accepted = true
}
}
TextArea {
id: textEdit1
objectName: "textEdit1"
anchors.fill: parent
clip: true
textFormat: Text.AutoText
visible: true
font.pixelSize: 12
z: 99
hoverEnabled: false
}
}
}
}
Rectangle {
id: mainView
objectName: "mainView"
Layout.minimumWidth: 100
Layout.fillWidth: false
Button {
id: button1
objectName: "btnAdd"
x: 8
y: 8
text: qsTr("Add")
onClicked: sv.addLst("fail")
}
Button {
id: button2
x: 8
y: 49
text: qsTr("Remove")
objectName: "btnRem"
}
Button {
id: button3
x: 8
y: 90
text: qsTr("Button ")
objectName: "btnMem"
}
}
}
/*
menuBar: MenuBar {
Menu {
title: "&File"
MenuItem {
text: "Close"
shortcut: StandardKey.Quit
}
}
Menu {
title: "&Edit"
MenuItem {
text: "quick edit"
objectName: "mnuEdit"
}
}
Menu {
title: "Window"
MenuItem {
text: "Display"
objectName: "mnuDisplay"
}
}
Menu {
MenuItem {
text: "&help"
}
}
}
*/
Menu {
objectName: "mnuCtx"
title: "new image..."
MenuItem {
objectName: "mnuImgPick"
text: "new Image..."
onTriggered: imgpicker.open()
}
}
}

View File

@ -1,35 +0,0 @@
//https://gist.github.com/elpuri/3753756
import QtQuick 2.4
import QtQuick.Controls 1.6
import QtQuick.Controls.Styles 1.4
TreeView {
id: view
anchors.fill: parent
anchors.margins: 2 * 12 + row.height
model: colors
alternatingRowColors: false
style: TreeViewStyle {
branchDelegate: Rectangle {
width: 16
height: 16
color: styleData.isExpanded ? "green" : "red"
}
frame: Rectangle {border {color: "blue"}}
backgroundColor: "blue"
}
TableViewColumn {
title: "Name"
role: "display"
resizable: true
delegate: Cell {
text: "hell"
}
}
}
/*##^## Designer {
D{i:0;autoSize:true;height:480;width:640}
}
##^##*/

View File

@ -1,28 +0,0 @@
import QtQuick 2.4
ListModel {
id: nestedModel
objectName: "nestedModel"
function get1() {
console.log(get(0))
return get(0)
}
ListElement {
title: "Cars"
collapsed: true
subItems: [
ListElement {
itemName: "tst"
},
ListElement {
itemName: "Tota"
},
ListElement {
itemName: "vy"
},
ListElement {
itemName: "Audio Adrenaline"
}
]
}
}

62
qml/cell.qml Normal file
View File

@ -0,0 +1,62 @@
import QtQuick 2.4
Rectangle {
objectName: "cellRect"
property int index: 0
height: 100
border.width: 2
border.color: "black"
anchors.right: parent.right
anchors.left: parent.left
Text {
id: cellText
enabled: true
objectName: "cellText"
text: ""
clip: true
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
anchors.fill: parent
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 2
MouseArea {
id: cellMouse
hoverEnabled: true
enabled: true
objectName: "cellMouse"
anchors.fill: parent
acceptedButtons: Qt.AllButtons
onMouseXChanged: cellHover()
onExited: focusChanged(focus)
function cellHover() {
if (containsMouse) {
parent.parent.border.color = "skyblue"
parent.parent.color = "darkblue"
parent.color = "white"
} else if (focus) {
parent.color = "black"
}
}
function notSelected() {
parent.parent.border.color = "black"
parent.parent.color = "white"
parent.color = "black"
cellHover()
}
function selected() {
parent.parent.border.color = "blue"
parent.color = "black"
parent.parent.color = "gainsboro"
cellHover()
}
}
}
}

View File

@ -1,15 +1,13 @@
import QtQuick 2.4 import QtQuick 2.2
import QtQuick.Dialogs 1.3 import QtQuick.Dialogs 1.0
FileDialog { FileDialog {
id: imgDialog id: imgDialog
title: "Please choose an image" title: "Please choose an image"
folder: shortcuts.home folder: shortcuts.home
onAccepted: { onAccepted: {
} }
onRejected: { onRejected: {
} }
Component.onCompleted: visible = true Component.onCompleted: visible = true
} }

View File

@ -13,11 +13,11 @@ Image {
anchors.left: parent.left anchors.left: parent.left
//cache: false //cache: false
MouseArea { MouseArea {
id: cellMouse id: cellMouse
hoverEnabled: true hoverEnabled: true
enabled: true enabled: true
objectName: "cellMouse" objectName: "cellMouse"
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.AllButtons acceptedButtons: Qt.AllButtons
} }
} }

View File

@ -1,7 +1,8 @@
import QtQuick 2.4 import QtQuick 2.4
import QtQuick.Controls 1.6 import QtQuick.Controls 1.4
import QtQuick.Layouts 1.11 import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.3 import QtQuick.Dialogs 1.2
//import Qt.labs.controls 1.0
ApplicationWindow { ApplicationWindow {
minimumHeight: 480 minimumHeight: 480
@ -10,14 +11,18 @@ ApplicationWindow {
ColorDialog { ColorDialog {
id: textClrDialog id: textClrDialog
//objectname: "textClrDialog" //objectname: "textClrDialog"
// @disable-check M16
title: "Please choose a color for the text" title: "Please choose a color for the text"
// @disable-check M16
showAlphaChannel: true showAlphaChannel: true
} }
ColorDialog { ColorDialog {
id: outlineClrDialog id: outlineClrDialog
//objectname: "outlineClrDialog" //objectname: "outlineClrDialog"
// @disable-check M16
title: "Please choose a color for the text" title: "Please choose a color for the text"
// @disable-check M16
showAlphaChannel: true showAlphaChannel: true
} }
@ -78,7 +83,7 @@ ApplicationWindow {
} }
ListView { ListView {
id: lstVerses id: lstVerses
objectName: "lstVerses" objectName: "lstVerses"
clip: true clip: true
highlight: Rectangle { highlight: Rectangle {
color: "lightsteelblue" color: "lightsteelblue"
@ -118,7 +123,7 @@ ApplicationWindow {
} }
ListView { ListView {
id: lstOrder id: lstOrder
objectName: "lstOrder" objectName: "lstOrder"
clip: true clip: true
highlight: Rectangle { highlight: Rectangle {
color: "lightsteelblue" color: "lightsteelblue"
@ -178,7 +183,12 @@ ApplicationWindow {
id: fontPicker id: fontPicker
objectName: "fontPicker" objectName: "fontPicker"
Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.alignment: Qt.AlignLeft | Qt.AlignTop
model: go.fontList.split("\n") model: go.fontLen
// @disable-check M16
/*delegate:Text {
text: go.fontList(index)
}*/
} }
SpinBox { SpinBox {
@ -212,9 +222,9 @@ ApplicationWindow {
ComboBox { ComboBox {
id: versePicker id: versePicker
objectName: "versePicker" objectName: "versePicker"
model: go.verses.split("\n") model: go.verseLen
/*// @disable-check M16 // @disable-check M16
delegate: Text { /* delegate: Text {
text: go.verses(index) text: go.verses(index)
}*/ }*/
} }
@ -222,15 +232,15 @@ ApplicationWindow {
ComboBox { ComboBox {
id: imgPicker id: imgPicker
objectName: "imgPicker" objectName: "imgPicker"
//model: go.img.split("\n") model: go.imgLen
/*// @disable-check M16 // @disable-check M16
delegate: Text { /*delegate: Text {
text: go.img(index) text: go.img(index)
}*/ }*/
} }
TextArea { TextArea {
id: txtVerse id: txtVerse
objectName: "txtVerse" objectName: "txtVerse"
width: 80 width: 80
height: 20 height: 20
text: qsTr("Text Edit") text: qsTr("Text Edit")

58
qrc.go

File diff suppressed because one or more lines are too long