Compare commits

...

10 Commits

Author SHA1 Message Date
lordwelch
43d53879ba commit everything I should have long ago 2019-05-06 03:15:55 -07:00
lordwelch
81572b7cc5 need this file for the url that is used in the program but I dont want it to actually package the qml into the program yet 2018-02-07 10:06:52 -08:00
lordwelch
a8534bd967 Now in in a not completely worthless state
Need to do some basic checks like bounds checking
And make the images show back up
2018-02-07 10:00:10 -08:00
lordwelch
7fc9aefdd7 Revert "moving away from GLFW mostly"
This reverts commit 73bbf9b01a300869904094bbd3c31b1ebc6e6679.

possibly getting back to a recoverable state
2018-02-06 20:50:49 -08:00
lordwelch
3c3c0e8904 Revert "remove gl crap"
This reverts commit 7cf75e4630b77c42504b0a07e0b72d8bdba27b4e.

possibly getting back to a recoverable state after the next revert
2018-02-06 20:48:54 -08:00
lordwelch
7cf75e4630 remove gl crap 2017-09-20 17:36:57 -07:00
lordwelch
73bbf9b01a moving away from GLFW mostly
switching to a list of lists
qml is way out of sync
need to figure out how much the signals need to be changed
and the best way to update the preview text for the qml
2017-02-05 13:57:50 -07:00
lordwelch
3569a7d502 adding another list element now works 2016-05-11 09:17:22 -07:00
lordwelch
636e3e42ed update listmodel
start on making append work
2016-05-10 10:27:32 -07:00
lordwelch
7e741afd9f change to qrc
change to listview
2016-05-10 09:43:49 -07:00
19 changed files with 826 additions and 1027 deletions

1
.gitignore vendored
View File

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

242
cmd/main.go Normal file
View File

@ -0,0 +1,242 @@
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
View File

@ -1,163 +0,0 @@
// 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
}
}

61
image.go Normal file
View File

@ -0,0 +1,61 @@
// 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")
}

View File

@ -1,172 +0,0 @@
// 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))
}

298
main.go
View File

@ -1,198 +1,208 @@
// PresentationApp project main.go
//go:generate genqrc qml
package main
import (
"fmt"
"image"
"image/color"
"os"
"path/filepath"
"github.com/go-gl/glfw/v3.1/glfw"
"github.com/kardianos/osext"
"github.com/lordwelch/qml"
"gopkg.in/gographics/imagick.v2/imagick"
"github.com/limetext/qml-go"
)
//Bool type i'm lazy wanted a toggle function
type Bool bool
type Cell struct {
Font Font
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 {
FontList []string
FontLen int
Verses []string
VerseLen int
VerseOrder []string
OrderLen int
Img []string
ImgLen int
FontList string
Verses string
VerseOrder string
}
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
type service []collection
var (
path string
slides slide
err error
currentService = new(service)
err error
path string
slides collection
)
func main() {
if err = qml.Run(run); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
win.Destroy()
glfw.PollEvents()
glfw.Terminate()
}
func run() error {
imagick.Initialize()
engine = qml.NewEngine()
QML = &qmlVar{}
path = "qrc:///qml"
findFonts()
engine.Context().SetVar("go", QML)
findfonts()
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/")
mainQml, err = engine.LoadFile(path + "/main.qml")
err = qmlWindows()
if err != nil {
return err
}
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
currentService.Init(1)
//image is ready for imageprovider
imgready = true
window.Show()
window2.Show()
edtQmlShow()
slides[0].clearcache()
displayImg = DisplayWindow.Root().ObjectByName("displayImage")
serviceObject = serviceQml.Create(engine.Context())
serviceObject.Set("parent", MainWindow.ObjectByName("scview"))
serviceObject.Call("addLst", "not")
//edtQmlShow()
qml.RunMain(glInit)
MainWindow.Wait()
slides.destroy()
fmt.Println(len(*currentService))
window.Wait()
imagick.Terminate()
return nil
}
//Adds a new cell
func (sl *slide) add( /*cl *cell*/ ) {
var cl cell
cl.Init()
//gets the length so that the index is valid
cl.index = len(*sl)
func (sv *service) Init(num int) {
if num <= 0 {
num = 1
}
//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)
//problems occur otherwise
*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)
}
func (cl *cell) Init() {
cl.text = "hello this is text\nhaha\nhdsjfklfhaskjd"
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.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
}
//(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
}
//Toggle, lazy wanted a func for it
func (bl *Bool) Toggle() {
if *bl == false {
*bl = true
} else {
*bl = false
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
func (sl *collection) add(text string) {
var (
cl Cell
i = len(*sl)
)
if len(text) <= 0 {
text = "Slide" + fmt.Sprint(i)
}
cl.Init()
//keep the pointer/dereference (i'm not sure which it is)
//problems occur otherwise
// now Im not an idiot and I know what this does
*sl = append(*sl, &cl)
}
// remove copied from github.com/golang/go/wiki/SliceTricks
func (sl *collection) remove(i int) {
cl := (*sl)[i]
cl.text = ""
MainWindow.ObjectByName("gridRect").Set("count", MainWindow.ObjectByName("gridRect").Int("count")-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() {
for i := len(*sl); i > 0; i-- {
sl.remove(i - 1)
}
}
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
func (cl cell) String() string {
func (cl Cell) String() string {
return fmt.Sprintf("Index: %d \nText: %s\n", cl.index, cl.text)
}

253
main.qml
View File

@ -1,253 +0,0 @@
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,203 +2,20 @@
package main
import (
"fmt"
"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
func imgProvider(id string, width, height int) image.Image {
var img1 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)
// i1 := strings.Index(id, `;`)
// i, _ := strconv.Atoi(id[:i1])
// img1 = 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
}
//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)
}

View File

@ -1,12 +0,0 @@
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
}

37
qml/Cell.qml Normal file
View File

@ -0,0 +1,37 @@
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
}
}
}
}

21
qml/Display.qml Normal file
View File

@ -0,0 +1,21 @@
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

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

159
qml/Main.qml Normal file
View File

@ -0,0 +1,159 @@
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()
}
}
}

35
qml/Service.qml Normal file
View File

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

28
qml/Sublist.qml Normal file
View File

@ -0,0 +1,28 @@
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"
}
]
}
}

View File

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

58
qrc.go Normal file

File diff suppressed because one or more lines are too long