commit everything I should have long ago
This commit is contained in:
parent
81572b7cc5
commit
43d53879ba
242
cmd/main.go
Normal file
242
cmd/main.go
Normal 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()
|
||||
}
|
57
glfw.go
57
glfw.go
@ -1,57 +0,0 @@
|
||||
// PresentationApp project glfw.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-gl/glfw/v3.1/glfw"
|
||||
)
|
||||
|
||||
var (
|
||||
monitorHeight int // displayed width
|
||||
monitors []*glfw.Monitor
|
||||
monitorWidth int // displayed height
|
||||
projectorMonitor *glfw.Monitor
|
||||
)
|
||||
|
||||
func checkMon() {
|
||||
monitors = glfw.GetMonitors()
|
||||
|
||||
if i := len(monitors); i < 2 {
|
||||
fmt.Println("You only have 1 monitor!!!!!!!!!!! :-P")
|
||||
monitorWidth = 800
|
||||
monitorHeight = 600
|
||||
|
||||
projectorMonitor = monitors[0]
|
||||
} else {
|
||||
fmt.Printf("You have %d monitors\n", i)
|
||||
monitorWidth = monitors[1].GetVideoMode().Width
|
||||
monitorHeight = monitors[1].GetVideoMode().Height
|
||||
projectorMonitor = monitors[1]
|
||||
|
||||
}
|
||||
monitorInfo()
|
||||
|
||||
}
|
||||
|
||||
func monitorInfo() {
|
||||
fmt.Println(len(monitors))
|
||||
for _, mon := range monitors {
|
||||
fmt.Printf("Monitor name: %s\n", mon.GetName())
|
||||
x, y := mon.GetPos()
|
||||
fmt.Printf("Position: %v, %v\n", x, y)
|
||||
fmt.Printf("Size: %v x %v\n", mon.GetVideoMode().Width, mon.GetVideoMode().Height)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func glInit() {
|
||||
if err = glfw.Init(); err == nil {
|
||||
checkMon()
|
||||
DisplayWindow.Root().Set("height", monitorHeight)
|
||||
DisplayWindow.Root().Set("width", monitorWidth)
|
||||
DisplayWindow.Root().Set("x", 0)
|
||||
DisplayWindow.Root().Set("y", 0)
|
||||
}
|
||||
}
|
61
image.go
Normal file
61
image.go
Normal 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")
|
||||
}
|
171
imagick.go
171
imagick.go
@ -1,171 +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.image.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 = out.String()
|
||||
}
|
||||
|
||||
func round(a float64) int {
|
||||
if a < 0 {
|
||||
return int(math.Ceil(a - 0.5))
|
||||
}
|
||||
return int(math.Floor(a + 0.5))
|
||||
}
|
52
main.go
52
main.go
@ -5,45 +5,46 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"os"
|
||||
|
||||
"github.com/go-gl/glfw/v3.1/glfw"
|
||||
"github.com/limetext/qml-go"
|
||||
|
||||
"gopkg.in/gographics/imagick.v2/imagick"
|
||||
)
|
||||
|
||||
type Cell struct {
|
||||
Font Font
|
||||
image Image
|
||||
index, collectionIndex int
|
||||
qmlObject qml.Object
|
||||
text string
|
||||
textVisible bool
|
||||
}
|
||||
|
||||
type collection []*Cell
|
||||
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 {
|
||||
img *imagick.MagickWand
|
||||
imgSource string
|
||||
qmlImage qml.Object
|
||||
path string
|
||||
original image.Image
|
||||
resized image.Image
|
||||
}
|
||||
|
||||
type qmlVar struct {
|
||||
FontList string
|
||||
Verses string
|
||||
VerseOrder string
|
||||
//Img string
|
||||
}
|
||||
|
||||
type service []collection
|
||||
@ -56,7 +57,6 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
if err = qml.Run(run); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
@ -69,7 +69,6 @@ func run() error {
|
||||
engine = qml.NewEngine()
|
||||
QML = &qmlVar{}
|
||||
path = "qrc:///qml"
|
||||
imagick.Initialize()
|
||||
findFonts()
|
||||
|
||||
engine.Context().SetVar("go", QML)
|
||||
@ -82,16 +81,13 @@ func run() error {
|
||||
|
||||
currentService.Init(1)
|
||||
|
||||
//signals for whole qml
|
||||
setSignals()
|
||||
|
||||
//image is ready for imageprovider
|
||||
imgready = true
|
||||
|
||||
displayImg = DisplayWindow.Root().ObjectByName("displayImage")
|
||||
serviceObject = serviceQml.Create(engine.Context())
|
||||
serviceObject.Set("parent", MainWindow.ObjectByName("data1"))
|
||||
serviceObject.Call("addLst", "shit")
|
||||
serviceObject.Set("parent", MainWindow.ObjectByName("scview"))
|
||||
serviceObject.Call("addLst", "not")
|
||||
|
||||
//edtQmlShow()
|
||||
qml.RunMain(glInit)
|
||||
@ -99,7 +95,6 @@ func run() error {
|
||||
slides.destroy()
|
||||
fmt.Println(len(*currentService))
|
||||
|
||||
imagick.Terminate()
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -174,21 +169,12 @@ func (sl *collection) add(text string) {
|
||||
//problems occur otherwise
|
||||
// now Im not an idiot and I know what this does
|
||||
*sl = append(*sl, &cl)
|
||||
|
||||
//seperate image object in QML
|
||||
cl.image.qmlImage.Set("source", fmt.Sprintf("image://images/cell;%d", cl.index))
|
||||
cl.setSignal()
|
||||
//give QML the text
|
||||
|
||||
}
|
||||
|
||||
//(slide) remove copied from github.com/golang/go/wiki/SliceTricks
|
||||
// remove copied from github.com/golang/go/wiki/SliceTricks
|
||||
func (sl *collection) remove(i int) {
|
||||
cl := (*sl)[i]
|
||||
cl.text = ""
|
||||
cl.image.qmlImage.Destroy()
|
||||
cl.qmlObject.Destroy()
|
||||
cl.image.img.Destroy()
|
||||
MainWindow.ObjectByName("gridRect").Set("count", MainWindow.ObjectByName("gridRect").Int("count")-1)
|
||||
cl.index = -1
|
||||
|
||||
@ -214,20 +200,6 @@ func (cl *Cell) Init() {
|
||||
cl.Font.outlineSize = 1
|
||||
cl.Font.size = 35
|
||||
cl.Font.x, cl.Font.y = 10, 30
|
||||
|
||||
cl.qmlObject = cellQml.Create(engine.Context())
|
||||
cl.image.qmlImage = cl.qmlObject.ObjectByName("cellImg")
|
||||
|
||||
//load image
|
||||
cl.image.img = imagick.NewMagickWand()
|
||||
cl.image.img.ReadImage("logo:")
|
||||
|
||||
}
|
||||
|
||||
func (cl *Cell) Select() {
|
||||
selectedCell = cl.index
|
||||
cl.qmlObject.ObjectByName("cellMouse").Call("selected")
|
||||
|
||||
}
|
||||
|
||||
//not really needed
|
||||
|
207
qml.go
207
qml.go
@ -3,220 +3,19 @@ package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/limetext/qml-go"
|
||||
)
|
||||
|
||||
var (
|
||||
selectedCell int //the focused cell
|
||||
rightClickCell int //the cell that was last right clicked
|
||||
cellQml qml.Object //file for the cell object
|
||||
mainQml qml.Object //main QML file
|
||||
editQml qml.Object
|
||||
textEdit qml.Object
|
||||
displayQml qml.Object
|
||||
displayImg qml.Object
|
||||
DisplayWindow *qml.Window
|
||||
MainWindow *qml.Window
|
||||
songEditWindow *qml.Window
|
||||
serviceObject qml.Object
|
||||
serviceQml qml.Object
|
||||
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 qmlWindows() error {
|
||||
mainQml, err = engine.LoadFile(path + "/Main.qml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
displayQml, err = engine.LoadFile(path + "/Display.qml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
editQml, err = engine.LoadFile(path + "/SongEdit.qml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cellQml, err = engine.LoadFile(path + "/Cell.qml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceQml, err = engine.LoadFile(path + "/Service.qml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
MainWindow = mainQml.CreateWindow(engine.Context())
|
||||
songEditWindow = editQml.CreateWindow(engine.Context())
|
||||
DisplayWindow = displayQml.CreateWindow(engine.Context())
|
||||
|
||||
textEdit = MainWindow.ObjectByName("textEdit")
|
||||
return nil
|
||||
}
|
||||
|
||||
func showWindows() {
|
||||
MainWindow.Show()
|
||||
songEditWindow.Show()
|
||||
DisplayWindow.Show()
|
||||
}
|
||||
|
||||
/*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.qmlObject.ObjectByName("cellMouse").On("clicked", func(mouseEvent qml.Object) {
|
||||
btn := mouseEvent.Property("button")
|
||||
//right click
|
||||
if btn == 2 {
|
||||
//context menu
|
||||
MainWindow.ObjectByName("mnuCtx").Call("popup")
|
||||
rightClickCell = cl.index
|
||||
} else {
|
||||
//left click
|
||||
//select and update image preview for cell
|
||||
cl.Select()
|
||||
}
|
||||
//update image preview
|
||||
cl.clearcache()
|
||||
})
|
||||
|
||||
cl.image.qmlImage.ObjectByName("cellMouse").On("clicked", func(mouseEvent qml.Object) {
|
||||
btn := mouseEvent.Property("button")
|
||||
//right click
|
||||
if btn == 2 {
|
||||
//context menu
|
||||
MainWindow.ObjectByName("mnuCtx").Call("popup")
|
||||
rightClickCell = cl.index
|
||||
} else {
|
||||
//left click
|
||||
//select and update image preview for cell
|
||||
cl.Select()
|
||||
}
|
||||
})
|
||||
|
||||
cl.qmlObject.ObjectByName("cellMouse").On("focusChanged", func(focus bool) {
|
||||
if focus {
|
||||
cl.qmlObject.ObjectByName("cellMouse").Call("selected")
|
||||
} else {
|
||||
cl.qmlObject.ObjectByName("cellMouse").Call("notSelected")
|
||||
}
|
||||
})
|
||||
|
||||
cl.qmlObject.ObjectByName("cellMouse").On("doubleClicked", func() {
|
||||
if quickEdit {
|
||||
//cover the cell with the text edit
|
||||
textEdit.Set("cell", cl.index)
|
||||
textEdit.Set("x", cl.qmlObject.Int("x"))
|
||||
textEdit.Set("y", cl.qmlObject.Int("y"))
|
||||
textEdit.Set("height", cl.qmlObject.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() {
|
||||
MainWindow.ObjectByName("imgpicker").On("accepted", func() {
|
||||
//delete file:// from url
|
||||
url := filepath.Clean(strings.TrimPrefix(MainWindow.ObjectByName("imgpicker").String("fileUrl"), "file:"))
|
||||
|
||||
//replace new image
|
||||
slides[rightClickCell].image.img.Clear()
|
||||
slides[rightClickCell].image.img.ReadImage(url)
|
||||
})
|
||||
|
||||
MainWindow.ObjectByName("btnAdd").On("clicked", func() {
|
||||
slides.add("not")
|
||||
})
|
||||
|
||||
MainWindow.ObjectByName("btnRem").On("clicked", func() {
|
||||
slides.remove(len(slides) - 1)
|
||||
})
|
||||
|
||||
MainWindow.ObjectByName("btnMem").On("clicked", func() {
|
||||
//run GC
|
||||
debug.FreeOSMemory()
|
||||
})
|
||||
|
||||
MainWindow.ObjectByName("mnuEdit").On("triggered", func() {
|
||||
quickEdit = !quickEdit
|
||||
})
|
||||
|
||||
textEdit.ObjectByName("textEdit1").On("focusChanged", func(focus bool) {
|
||||
var (
|
||||
str string
|
||||
cell *Cell
|
||||
)
|
||||
|
||||
if !focus {
|
||||
//set text back to the cell
|
||||
str = textEdit.ObjectByName("textEdit1").String("text")
|
||||
cell = slides[textEdit.Int("cell")]
|
||||
if textEdit.Bool("txt") {
|
||||
cell.qmlObject.ObjectByName("cellText").Set("text", str)
|
||||
cell.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])
|
||||
img1 = 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))
|
||||
}
|
||||
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.image.qmlImage.String("source")
|
||||
i := strings.Index(str, `;`)
|
||||
str1 := str[:i]
|
||||
i1, _ := strconv.Atoi(str[i+1:])
|
||||
str = str1 + `;` + strconv.Itoa(i1+1)
|
||||
//fmt.Println("new source (click): ", str)
|
||||
cl.image.qmlImage.Set("source", str)
|
||||
}
|
||||
|
98
qml/Cell.qml
98
qml/Cell.qml
@ -1,83 +1,37 @@
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Layouts 1.11
|
||||
|
||||
Rectangle {
|
||||
objectName: "cellRect"
|
||||
property int index: 0
|
||||
id: itm
|
||||
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"
|
||||
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
|
||||
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()
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
Image {
|
||||
id: img
|
||||
antialiasing: true
|
||||
source: "image://images/"
|
||||
objectName: "cellImg"
|
||||
property int index: 0
|
||||
height: 100
|
||||
transformOrigin: Item.TopLeft
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
//cache: false
|
||||
MouseArea {
|
||||
id: imgMouse
|
||||
hoverEnabled: true
|
||||
enabled: true
|
||||
objectName: "cellMouse"
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.AllButtons
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls 2.4
|
||||
|
||||
ApplicationWindow {
|
||||
flags: Qt.MaximumSize
|
||||
@ -13,5 +13,9 @@ ApplicationWindow {
|
||||
antialiasing: true
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*##^## Designer {
|
||||
D{i:0;autoSize:true;height:480;width:640}
|
||||
}
|
||||
##^##*/
|
||||
|
@ -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
|
||||
}
|
||||
}
|
291
qml/Main.qml
291
qml/Main.qml
@ -1,9 +1,9 @@
|
||||
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
|
||||
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
|
||||
@ -12,23 +12,108 @@ ApplicationWindow {
|
||||
objectName: "applicationWindow1"
|
||||
minimumWidth: 500
|
||||
minimumHeight: 500
|
||||
width: 1000
|
||||
height: 600
|
||||
|
||||
FileDialog {
|
||||
id: imgpicker
|
||||
// @disable-check M16
|
||||
title: "Choose an image for this slide"
|
||||
// @disable-check M16
|
||||
objectName: "imgpicker"
|
||||
title: "Choose an image for this slide"
|
||||
}
|
||||
|
||||
Action {
|
||||
id: aboutAction
|
||||
text: "About"
|
||||
onTriggered: aboutDialog.open()
|
||||
}
|
||||
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"
|
||||
@ -55,13 +140,13 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
Menu {
|
||||
title: "&Help"
|
||||
|
||||
MenuItem {
|
||||
action: aboutAction
|
||||
text: "&help"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
Menu {
|
||||
objectName: "mnuCtx"
|
||||
title: "new image..."
|
||||
@ -71,174 +156,4 @@ ApplicationWindow {
|
||||
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: 1
|
||||
property int expcount: 1
|
||||
|
||||
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: data1.childrenRect.height //gridRect.count * 101
|
||||
|
||||
Rectangle {
|
||||
id: col1
|
||||
objectName: "col1"
|
||||
width: gridData.width / 2
|
||||
color: "#00000000"
|
||||
transformOrigin: Item.TopLeft
|
||||
border.width: 0
|
||||
height: data1.childrenRect.height
|
||||
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
|
||||
clip: true
|
||||
height: data1.childrenRect.height
|
||||
}
|
||||
}
|
||||
|
||||
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") + data1.childrenRect.height
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button2
|
||||
x: 8
|
||||
y: 43
|
||||
text: qsTr("Button ")
|
||||
objectName: "btnRem"
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button3
|
||||
x: 8
|
||||
y: 78
|
||||
text: qsTr("Button ")
|
||||
objectName: "btnMem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
216
qml/Service.qml
216
qml/Service.qml
@ -1,197 +1,35 @@
|
||||
//https://gist.github.com/elpuri/3753756
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.6
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
Item {
|
||||
id: rt
|
||||
property ListElement def: ListElement {
|
||||
property string cellText: "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
|
||||
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
|
||||
<html >
|
||||
|
||||
<head>
|
||||
<meta content=\"text/html; charset=utf-8\" http-equiv=\"Content-Type\" />
|
||||
<title>Untitled 1</title>
|
||||
<style type=\"text/css\">
|
||||
.auto-style2 {
|
||||
font-family: \"Times New Roman\", Times, serif;
|
||||
font-size: small;
|
||||
}
|
||||
.auto-style3 {
|
||||
background-color: #FFFF00;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p><b>Header text</b><br/></p>
|
||||
<span class=\"auto-style3\">This is paragraph text</span>
|
||||
|
||||
<hr />
|
||||
</body>
|
||||
|
||||
</html>"
|
||||
property int collectionIndex: 0
|
||||
property string imageSource: "image://images/list:;cell:"
|
||||
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"
|
||||
}
|
||||
|
||||
Component.onCompleted: addLst("Haha :-P")
|
||||
height: ((lst.count) * 50) + (lst.subCount * 100)
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
function remove(List, index) {
|
||||
lst.subCount--
|
||||
nestedModel.get(List).subItems.remove(index, 1)
|
||||
}
|
||||
|
||||
function pop(List) {
|
||||
lst.subCount--
|
||||
nestedModel.get(List).subItems.remove(nestedModel.get(
|
||||
List).subItems.count - 1, 1)
|
||||
}
|
||||
function newdef(index, txt, src) {
|
||||
var item = Object.create(def)
|
||||
item.collectionIndex = index
|
||||
item.text = txt
|
||||
item.imageSource = src
|
||||
return item
|
||||
}
|
||||
function remLst() {
|
||||
nestedModel.remove(nestedModel.count - 1, 1)
|
||||
}
|
||||
|
||||
function apppend(List, obj) {
|
||||
lst.subCount++
|
||||
nestedModel.get(List).subItems.append(obj)
|
||||
}
|
||||
|
||||
function insert(List, index, obj) {
|
||||
lst.subCount++
|
||||
nestedModel.get(List).subItems.insert(index, obj)
|
||||
}
|
||||
|
||||
function get(List, index) {
|
||||
return nestedModel.get(List).subItems.get(index)
|
||||
}
|
||||
|
||||
function set(List, index, obj) {
|
||||
nestedModel.get(List).subItems.set(index, obj)
|
||||
}
|
||||
|
||||
function addLst(str) {
|
||||
var newCollection
|
||||
var i = 0
|
||||
var temp = Qt.createComponent("Sublist.qml").createObject(rt, {
|
||||
|
||||
})
|
||||
|
||||
newCollection = temp.get(0)
|
||||
newCollection.name = str
|
||||
newCollection.subItems.clear()
|
||||
for (i = 0; i < 1; i++) {
|
||||
newCollection.subItems.append(newdef(nestedModel.count, "idiot"))
|
||||
}
|
||||
|
||||
nestedModel.append(newCollection)
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: lst
|
||||
anchors.fill: parent
|
||||
y: 0
|
||||
height: ((lst.count) * 55) + (lst.subCount * 100)
|
||||
interactive: false
|
||||
property int subCount: 0
|
||||
model: nestedModel
|
||||
delegate: Component {
|
||||
id: categoryDelegate
|
||||
Column {
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
|
||||
//width: 200
|
||||
Rectangle {
|
||||
id: categoryItem
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
border.color: "black"
|
||||
border.width: 5
|
||||
color: "white"
|
||||
height: 50
|
||||
|
||||
//width: 200
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: 15
|
||||
font.pixelSize: 24
|
||||
text: name
|
||||
clip: true
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 15
|
||||
anchors.leftMargin: 5
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: "red"
|
||||
width: 30
|
||||
height: 30
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 15
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
// Toggle the 'collapsed' property
|
||||
onClicked: {
|
||||
nestedModel.setProperty(index, "collapsed",
|
||||
!collapsed)
|
||||
if (!nestedModel.get(index).collapsed) {
|
||||
lst.subCount = lst.subCount + subItemLoader.subItemModel.count
|
||||
} else {
|
||||
lst.subCount = lst.subCount - subItemLoader.subItemModel.count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: subItemLoader
|
||||
|
||||
// This is a workaround for a bug/feature in the Loader element. If sourceComponent is set to null
|
||||
// the Loader element retains the same height it had when sourceComponent was set. Setting visible
|
||||
// to false makes the parent Column treat it as if it's height was 0.
|
||||
visible: !collapsed
|
||||
property variant subItemModel: subItems
|
||||
sourceComponent: subItemColumnDelegate
|
||||
onStatusChanged: if (status == Loader.Ready) {
|
||||
item.model = subItemModel
|
||||
}
|
||||
}
|
||||
}
|
||||
TableViewColumn {
|
||||
title: "Name"
|
||||
role: "display"
|
||||
resizable: true
|
||||
delegate: Cell {
|
||||
text: "hell"
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: subItemColumnDelegate
|
||||
Column {
|
||||
property alias model: subItemRepeater.model
|
||||
|
||||
width: rt.width
|
||||
Repeater {
|
||||
id: subItemRepeater
|
||||
objectName: "repeater"
|
||||
delegate: Cell {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: nestedModel
|
||||
objectName: "nestedModel"
|
||||
}
|
||||
}
|
||||
|
||||
/*##^## Designer {
|
||||
D{i:0;autoSize:true;height:480;width:640}
|
||||
}
|
||||
##^##*/
|
||||
|
@ -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
|
||||
@ -79,7 +78,7 @@ ApplicationWindow {
|
||||
}
|
||||
ListView {
|
||||
id: lstVerses
|
||||
objectName: "lstVerses"
|
||||
objectName: "lstVerses"
|
||||
clip: true
|
||||
highlight: Rectangle {
|
||||
color: "lightsteelblue"
|
||||
@ -119,7 +118,7 @@ ApplicationWindow {
|
||||
}
|
||||
ListView {
|
||||
id: lstOrder
|
||||
objectName: "lstOrder"
|
||||
objectName: "lstOrder"
|
||||
clip: true
|
||||
highlight: Rectangle {
|
||||
color: "lightsteelblue"
|
||||
@ -180,11 +179,6 @@ ApplicationWindow {
|
||||
objectName: "fontPicker"
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
model: go.fontList.split("\n")
|
||||
/*// @disable-check M16
|
||||
delegate:Text {
|
||||
text: go.fontList(index)
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
SpinBox {
|
||||
@ -228,7 +222,7 @@ ApplicationWindow {
|
||||
ComboBox {
|
||||
id: imgPicker
|
||||
objectName: "imgPicker"
|
||||
model: go.img.split("\n")
|
||||
//model: go.img.split("\n")
|
||||
/*// @disable-check M16
|
||||
delegate: Text {
|
||||
text: go.img(index)
|
||||
@ -236,7 +230,7 @@ ApplicationWindow {
|
||||
}
|
||||
TextArea {
|
||||
id: txtVerse
|
||||
objectName: "txtVerse"
|
||||
objectName: "txtVerse"
|
||||
width: 80
|
||||
height: 20
|
||||
text: qsTr("Text Edit")
|
||||
|
@ -8,7 +8,7 @@ ListModel {
|
||||
return get(0)
|
||||
}
|
||||
ListElement {
|
||||
categoryName: "Cars"
|
||||
title: "Cars"
|
||||
collapsed: true
|
||||
subItems: [
|
||||
ListElement {
|
||||
|
@ -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
|
||||
}
|
||||
|
173
tst.qml
173
tst.qml
@ -1,173 +0,0 @@
|
||||
//https://gist.github.com/elpuri/3753756
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
|
||||
ApplicationWindow {
|
||||
id: app1
|
||||
minimumWidth: 200
|
||||
minimumHeight: 50
|
||||
|
||||
Item {
|
||||
id: tst4
|
||||
height: 50 + ((tst3.count-1)*50) + (tst3.subCount * 40)
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
|
||||
|
||||
ListView {
|
||||
id: tst3
|
||||
anchors.fill: parent
|
||||
property int subCount: 0
|
||||
model: nestedModel
|
||||
delegate: Component {
|
||||
id: categoryDelegate
|
||||
Column {
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
|
||||
//width: 200
|
||||
Rectangle {
|
||||
id: categoryItem
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
border.color: "black"
|
||||
border.width: 5
|
||||
color: "white"
|
||||
height: 50
|
||||
|
||||
//width: 200
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: 15
|
||||
font.pixelSize: 24
|
||||
text: categoryName
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: "red"
|
||||
width: 30
|
||||
height: 30
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 15
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
// Toggle the 'collapsed' property
|
||||
onClicked: {
|
||||
nestedModel.setProperty(index, "collapsed", !collapsed)
|
||||
if (!nestedModel.get(index).collapsed) {
|
||||
tst3.subCount = tst3.subCount + subItemLoader.subItemModel.count
|
||||
} else {
|
||||
tst3.subCount = tst3.subCount - subItemLoader.subItemModel.count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: subItemLoader
|
||||
|
||||
// This is a workaround for a bug/feature in the Loader element. If sourceComponent is set to null
|
||||
// the Loader element retains the same height it had when sourceComponent was set. Setting visible
|
||||
// to false makes the parent Column treat it as if it's height was 0.
|
||||
visible: !collapsed
|
||||
property variant subItemModel: subItems
|
||||
sourceComponent: collapsed ? null : subItemColumnDelegate
|
||||
onStatusChanged: if (status == Loader.Ready)
|
||||
item.model = subItemModel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: subItemColumnDelegate
|
||||
Column {
|
||||
property alias model: subItemRepeater.model
|
||||
|
||||
width: tst4.width
|
||||
Repeater {
|
||||
id: subItemRepeater
|
||||
delegate: Rectangle {
|
||||
color: "#cccccc"
|
||||
height: 40
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
//width: 200
|
||||
border.color: "black"
|
||||
border.width: 2
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: 30
|
||||
font.pixelSize: 18
|
||||
text: itemName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: nestedModel
|
||||
ListElement {
|
||||
categoryName: "Cars"
|
||||
collapsed: true
|
||||
subItems: [
|
||||
ListElement {
|
||||
itemName: "Nissan"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Toyota"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Chevy"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Audi"
|
||||
}
|
||||
]
|
||||
}
|
||||
ListElement {
|
||||
categoryName: "Cars"
|
||||
collapsed: true
|
||||
subItems: [
|
||||
ListElement {
|
||||
itemName: "Nissan"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Toyota"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Chevy"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Audi"
|
||||
}
|
||||
]
|
||||
}
|
||||
ListElement {
|
||||
categoryName: "Cars"
|
||||
collapsed: true
|
||||
subItems: [
|
||||
ListElement {
|
||||
itemName: "Nissan"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Toyota"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Chevy"
|
||||
},
|
||||
ListElement {
|
||||
itemName: "Audi"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user