feat: init
This commit is contained in:
commit
95fa3784f7
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
ui/*.glade~
|
||||
dist/
|
16
README.md
Normal file
16
README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# hui
|
||||
|
||||
> 🚧 **Extremely WIP** 🚧
|
||||
|
||||
A [GTK](https://gtk.org) desktop app for publishing [static websites](https://en.wikipedia.org/wiki/Static_web_page) with [Hugo](https://gohugo.io).
|
||||
|
||||
Inspired by [`another.varia.zone`](https://another.varia.zone/) and [Rebuilding a Solar Powered Website](https://solar.lowtechmagazine.com/2023/06/rebuilding-a-solar-powered-website/).
|
||||
|
||||
## Preview
|
||||
|
||||
* [Initial setup (video)](https://d1.hackers.moe/gui/demotime1.mp4)
|
||||
* [Glade design workflow (image)](https://d1.hackers.moe/gui/glade.png)
|
||||
|
||||
## Planning
|
||||
|
||||
See [`#1`](https://git.coopcloud.tech/decentral1se/hui/issues/1).
|
127
cmd/hui/main.go
Normal file
127
cmd/hui/main.go
Normal file
@ -0,0 +1,127 @@
|
||||
// Package main is the application entrypoint.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/user"
|
||||
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
"varia.zone/hui/internal/bldr"
|
||||
"varia.zone/hui/internal/conf"
|
||||
"varia.zone/hui/internal/model"
|
||||
"varia.zone/hui/internal/ui"
|
||||
)
|
||||
|
||||
const appID = "zone.varia.hui"
|
||||
|
||||
func main() {
|
||||
application, err := gtk.ApplicationNew(appID, glib.APPLICATION_FLAGS_NONE)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to initialise GTK application: %s", err))
|
||||
}
|
||||
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to detect current user: %s", err))
|
||||
}
|
||||
|
||||
m := &model.Model{
|
||||
User: usr,
|
||||
}
|
||||
|
||||
application.Connect("activate", func() {
|
||||
builder, err := gtk.BuilderNewFromFile(conf.MainWindowGladeFile)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("main: unable to load '%s' from file: %s", conf.MainWindowGladeFile, err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
m.Builder = builder
|
||||
|
||||
if _, err := os.Stat(conf.HugoBinPath(m.User.HomeDir)); err != nil && os.IsNotExist(err) {
|
||||
if err := ui.SwitchStackPage(m, conf.InitStackPage); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
if err := ui.HideSiteButtons(m); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if err := ui.SwitchStackPage(m, conf.EmptyStackPage); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
if err := ui.PopulateOpenSiteMenu(m); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signals := map[string]interface{}{
|
||||
"hideErrorDialog": func() {
|
||||
if err := ui.HideErrorDialog(m); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialise": func() {
|
||||
if err := ui.Initialise(m); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
},
|
||||
"showNewSiteDialog": func() {
|
||||
if err := ui.ShowNewSiteDialog(m); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
},
|
||||
"hideNewSiteDialog": func() {
|
||||
if err := ui.HideNewSiteDialog(m); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
},
|
||||
"createNewSite": func() {
|
||||
if err := ui.CreateNewSite(m); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
},
|
||||
"previewSite": func() {
|
||||
if err := ui.PreviewSite(m); err != nil {
|
||||
if err := ui.ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
m.Builder.ConnectSignals(signals)
|
||||
|
||||
window, err := bldr.GetWindow(m.Builder, conf.MainWindow)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
window.Show()
|
||||
application.AddWindow(window)
|
||||
})
|
||||
|
||||
os.Exit(application.Run(os.Args))
|
||||
}
|
33
go.mod
Normal file
33
go.mod
Normal file
@ -0,0 +1,33 @@
|
||||
module varia.zone/hui
|
||||
|
||||
go 1.21.1
|
||||
|
||||
require (
|
||||
github.com/codeclysm/extract v2.2.0+incompatible
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.9 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/h2non/filetype v1.1.3 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/juju/errors v1.0.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
golang.org/x/crypto v0.24.0 // indirect
|
||||
golang.org/x/net v0.26.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
149
go.sum
Normal file
149
go.sum
Normal file
@ -0,0 +1,149 @@
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE=
|
||||
github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/codeclysm/extract v2.2.0+incompatible h1:q3wyckoA30bhUSiwdQezMqVhwd8+WGE64/GL//LtUhI=
|
||||
github.com/codeclysm/extract v2.2.0+incompatible/go.mod h1:2nhFMPHiU9At61hz+12bfrlpXSUrOnK+wR+KlGO4Uks=
|
||||
github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
|
||||
github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
||||
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/gotk3/gotk3 v0.6.4 h1:5ur/PRr86PwCG8eSj98D1eXvhrNNK6GILS2zq779dCg=
|
||||
github.com/gotk3/gotk3 v0.6.4/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
|
||||
github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56 h1:eR+xxC8qqKuPMTucZqaklBxLIT7/4L7dzhlwKMrDbj8=
|
||||
github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
|
||||
github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
|
||||
github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM=
|
||||
github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
|
||||
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
182
internal/bldr/get.go
Normal file
182
internal/bldr/get.go
Normal file
@ -0,0 +1,182 @@
|
||||
// Package bldr deals with Glade GTK* builder functionality.
|
||||
package bldr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
// GetBuilder retrieves a named builder.
|
||||
func GetBuilder(builderName string) (*gtk.Builder, error) {
|
||||
builder, err := gtk.BuilderNewFromFile(builderName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetBuilder: unable to BuilderNewFromFile: %s", err)
|
||||
}
|
||||
return builder, nil
|
||||
}
|
||||
|
||||
// GetAboutDialog retrieves a named about dialog.
|
||||
func GetAboutDialog(builder *gtk.Builder, widgetName string) (*gtk.AboutDialog, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetAboutDialog: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
dialog, ok := obj.(*gtk.AboutDialog)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetAboutDialog: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return dialog, nil
|
||||
}
|
||||
|
||||
// GetDialog retrieves a named dialog.
|
||||
func GetDialog(builder *gtk.Builder, widgetName string) (*gtk.Dialog, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetDialog: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
dialog, ok := obj.(*gtk.Dialog)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetDialog: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return dialog, nil
|
||||
}
|
||||
|
||||
// GetEntry retrieves a named entry.
|
||||
func GetEntry(builder *gtk.Builder, widgetName string) (*gtk.Entry, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetEntry: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
entry, ok := obj.(*gtk.Entry)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetEntry: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
// GetBox retrieves a named box.
|
||||
func GetBox(builder *gtk.Builder, widgetName string) (*gtk.Box, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetBox: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
box, ok := obj.(*gtk.Box)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetBox: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return box, nil
|
||||
}
|
||||
|
||||
// GetSpinner retrieves a named spinner.
|
||||
func GetSpinner(builder *gtk.Builder, widgetName string) (*gtk.Spinner, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetSpinner: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
spinner, ok := obj.(*gtk.Spinner)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetSpinner: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return spinner, nil
|
||||
}
|
||||
|
||||
// GetLabel retrieves a named label.
|
||||
func GetLabel(builder *gtk.Builder, widgetName string) (*gtk.Label, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetLabel: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
label, ok := obj.(*gtk.Label)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetLabel: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return label, nil
|
||||
}
|
||||
|
||||
// GetWindow retrieves a named window.
|
||||
func GetWindow(builder *gtk.Builder, widgetName string) (*gtk.Window, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetWindow: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
window, ok := obj.(*gtk.Window)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetWindow: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return window, nil
|
||||
}
|
||||
|
||||
// GetButton retrieves a named button.
|
||||
func GetButton(builder *gtk.Builder, widgetName string) (*gtk.Button, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetButton: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
button, ok := obj.(*gtk.Button)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetButton: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return button, nil
|
||||
}
|
||||
|
||||
// GetSeparator retrieves a named seperator.
|
||||
func GetSeparator(builder *gtk.Builder, widgetName string) (*gtk.Separator, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetSeparator: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
sep, ok := obj.(*gtk.Separator)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetSeparator: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return sep, nil
|
||||
}
|
||||
|
||||
// GetHeaderBar retrieves a named header bar.
|
||||
func GetHeaderBar(builder *gtk.Builder, widgetName string) (*gtk.HeaderBar, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetHeaderBar: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
headerBar, ok := obj.(*gtk.HeaderBar)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetHeaderBar: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return headerBar, nil
|
||||
}
|
||||
|
||||
// GetMenu retrieves a named menu.
|
||||
func GetMenu(builder *gtk.Builder, widgetName string) (*gtk.Menu, error) {
|
||||
obj, err := builder.GetObject(widgetName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetMenu: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
menu, ok := obj.(*gtk.Menu)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("GetMenu: unable to GetObject: '%s'", widgetName)
|
||||
}
|
||||
|
||||
return menu, nil
|
||||
}
|
6
internal/conf/bldr.go
Normal file
6
internal/conf/bldr.go
Normal file
@ -0,0 +1,6 @@
|
||||
// Package conf deals with application configuration.
|
||||
package conf
|
||||
|
||||
var (
|
||||
MainWindowGladeFile = "ui/hui.glade"
|
||||
)
|
36
internal/conf/dir.go
Normal file
36
internal/conf/dir.go
Normal file
@ -0,0 +1,36 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func GetHomeDir() (string, error) {
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("GetHomeDir: unable to retrieve current user")
|
||||
}
|
||||
|
||||
return usr.HomeDir, nil
|
||||
}
|
||||
|
||||
func DataDir(homeDir string) string {
|
||||
return filepath.Join(homeDir, ".hui")
|
||||
}
|
||||
|
||||
func HugoDir(homeDir string) string {
|
||||
return filepath.Join(DataDir(homeDir), "hugo")
|
||||
}
|
||||
|
||||
func HugoBinPath(homeDir string) string {
|
||||
return filepath.Join(HugoDir(homeDir), "hugo")
|
||||
}
|
||||
|
||||
func SitesDir(homeDir string) string {
|
||||
return filepath.Join(DataDir(homeDir), "sites")
|
||||
}
|
||||
|
||||
func NewSiteDir(homeDir, newSiteName string) string {
|
||||
return filepath.Join(DataDir(homeDir), "sites", newSiteName)
|
||||
}
|
13
internal/conf/hugo.go
Normal file
13
internal/conf/hugo.go
Normal file
@ -0,0 +1,13 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
// HugoVersion is the version of Hugo used.
|
||||
HugoVersion = "0.124.1"
|
||||
|
||||
// HugoReleaseURL is the URL where Hugo can be downloaded from.
|
||||
HugoReleaseURL = fmt.Sprintf("https://github.com/gohugoio/hugo/releases/download/v%s/hugo_extended_%s_linux-amd64.tar.gz", HugoVersion, HugoVersion)
|
||||
)
|
37
internal/conf/widget.go
Normal file
37
internal/conf/widget.go
Normal file
@ -0,0 +1,37 @@
|
||||
package conf
|
||||
|
||||
var (
|
||||
AboutDialog = "aboutDialog"
|
||||
ErrorDialog = "errorDialog"
|
||||
NewSiteDialog = "newSiteDialog"
|
||||
ExistingSiteDialog = "existingSiteDialog"
|
||||
|
||||
InitStackPage = "initStackPage"
|
||||
EmptyStackPage = "emptyStackPage"
|
||||
BusyStackPage = "busyStackPage"
|
||||
ContentStackPage = "contentStackPage"
|
||||
|
||||
InitSpinner = "initSpinner"
|
||||
|
||||
InitPromptBox = "initPromptBox"
|
||||
InitSpinnerBox = "initSpinnerBox"
|
||||
OpenSiteBox = "openSiteBox"
|
||||
|
||||
InitSpinnerLabel = "initSpinnerLabel"
|
||||
ErrorMessageLabel = "errorMessageLabel"
|
||||
BusyStackLabel = "busyStackLabel"
|
||||
|
||||
NewSiteNameEntry = "newSiteNameEntry"
|
||||
|
||||
MainWindow = "mainWindow"
|
||||
|
||||
CreateSiteButton = "createSiteButton"
|
||||
CreatePostButton = "createPostButton"
|
||||
PreviewButton = "previewButton"
|
||||
|
||||
HeaderBarSeparator = "headerBarSeparator"
|
||||
|
||||
HeaderBar = "headerBar"
|
||||
|
||||
OpenSiteMenu = "openSiteMenu"
|
||||
)
|
16
internal/model/model.go
Normal file
16
internal/model/model.go
Normal file
@ -0,0 +1,16 @@
|
||||
// Package model handles the application state API.
|
||||
package model
|
||||
|
||||
import (
|
||||
"os/user"
|
||||
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
// Model is the application internal state.
|
||||
type Model struct {
|
||||
Builder *gtk.Builder // Gtk builder
|
||||
User *user.User // System user
|
||||
CurrentSite string // The currently chosen site
|
||||
SiteNames []string // Existing site names
|
||||
}
|
31
internal/ui/about.go
Normal file
31
internal/ui/about.go
Normal file
@ -0,0 +1,31 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"varia.zone/hui/internal/bldr"
|
||||
"varia.zone/hui/internal/conf"
|
||||
"varia.zone/hui/internal/model"
|
||||
)
|
||||
|
||||
// ShowAboutDialog handles the show about dialog signal.
|
||||
func ShowAboutDialog(m *model.Model) error {
|
||||
dialog, err := bldr.GetAboutDialog(m.Builder, conf.AboutDialog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialog.Show()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HideAboutDialog handles the hide ainbout dialog signal.
|
||||
func HideAboutDialog(m *model.Model) error {
|
||||
dialog, err := bldr.GetAboutDialog(m.Builder, conf.AboutDialog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialog.Hide()
|
||||
|
||||
return nil
|
||||
}
|
41
internal/ui/error.go
Normal file
41
internal/ui/error.go
Normal file
@ -0,0 +1,41 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"varia.zone/hui/internal/bldr"
|
||||
"varia.zone/hui/internal/conf"
|
||||
"varia.zone/hui/internal/model"
|
||||
)
|
||||
|
||||
// ShowErrDialog raises a dialog dedicated to showing error messages.
|
||||
func ShowErrDialog(m *model.Model, uiErr error) error {
|
||||
dialog, err := bldr.GetDialog(m.Builder, conf.ErrorDialog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
label, err := bldr.GetLabel(m.Builder, conf.ErrorMessageLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
label.SetLabel(fmt.Sprintf("ERROR: %s", uiErr))
|
||||
label.Show()
|
||||
|
||||
dialog.Show()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HideErrorDialog handles the hide error dialog signal.
|
||||
func HideErrorDialog(m *model.Model) error {
|
||||
dialog, err := bldr.GetDialog(m.Builder, conf.ErrorDialog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialog.Hide()
|
||||
|
||||
return nil
|
||||
}
|
201
internal/ui/header.go
Normal file
201
internal/ui/header.go
Normal file
@ -0,0 +1,201 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
"varia.zone/hui/internal/bldr"
|
||||
"varia.zone/hui/internal/conf"
|
||||
"varia.zone/hui/internal/model"
|
||||
)
|
||||
|
||||
// SetHeaderBarSubtitle sets the header bar subtitle.
|
||||
func SetHeaderBarSubtitle(m *model.Model, siteName string) error {
|
||||
headerBar, err := bldr.GetHeaderBar(m.Builder, conf.HeaderBar)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SetHeaderBarSubtitle: unable to retrieve '%s': %s", conf.HeaderBar, err)
|
||||
}
|
||||
|
||||
headerBar.SetSubtitle(siteName)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getSiteButtons retrieves the site related header bar buttons.
|
||||
func getSiteButtons(m *model.Model) (*gtk.Box, *gtk.Button, error) {
|
||||
box, err := bldr.GetBox(m.Builder, conf.OpenSiteBox)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
btn, err := bldr.GetButton(m.Builder, conf.CreateSiteButton)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return box, btn, nil
|
||||
}
|
||||
|
||||
// ShowSiteButtons shows site related buttons.
|
||||
func ShowSiteButtons(m *model.Model) error {
|
||||
box, btn, err := getSiteButtons(m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ShowSiteButtons: %s", err)
|
||||
}
|
||||
|
||||
box.Show()
|
||||
btn.Show()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HideSiteButtons shows site related buttons.
|
||||
func HideSiteButtons(m *model.Model) error {
|
||||
box, btn, err := getSiteButtons(m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("HideSiteButtons: %s", err)
|
||||
}
|
||||
|
||||
box.Hide()
|
||||
btn.Hide()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getContentButtons(m *model.Model) (*gtk.Separator, []*gtk.Button, error) {
|
||||
sep, err := bldr.GetSeparator(m.Builder, conf.HeaderBarSeparator)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var btns []*gtk.Button
|
||||
for _, name := range []string{conf.CreatePostButton, conf.PreviewButton} {
|
||||
btn, err := bldr.GetButton(m.Builder, name)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
btns = append(btns, btn)
|
||||
}
|
||||
|
||||
return sep, btns, err
|
||||
}
|
||||
|
||||
// ShowContentButtons shows content related buttons.
|
||||
func ShowContentButtons(m *model.Model) error {
|
||||
sep, btns, err := getContentButtons(m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("HideContentButtons: %s", err)
|
||||
}
|
||||
|
||||
sep.Show()
|
||||
|
||||
for _, btn := range btns {
|
||||
btn.Show()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HideContentButtons shows content related buttons.
|
||||
func HideContentButtons(m *model.Model) error {
|
||||
sep, btns, err := getContentButtons(m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("HideContentButtons: %s", err)
|
||||
}
|
||||
|
||||
sep.Hide()
|
||||
|
||||
for _, btn := range btns {
|
||||
btn.Hide()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenMenuChoice responds to a clicked "existing menu" selection.
|
||||
func OpenMenuChoice(m *model.Model, menuItem *gtk.MenuItem) error {
|
||||
label := menuItem.GetLabel()
|
||||
splitLabel := strings.Split(label, " ")
|
||||
siteName := strings.TrimSpace(splitLabel[len(splitLabel)-1])
|
||||
|
||||
m.CurrentSite = siteName
|
||||
|
||||
if err := SetHeaderBarSubtitle(m, m.CurrentSite); err != nil {
|
||||
return fmt.Errorf("OpenMenuChoice: unable to set header bar subtitle: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// gatherSiteNames gathers the site names from disk.
|
||||
func gatherSiteNames(m *model.Model) error {
|
||||
sitesDir := conf.SitesDir(m.User.HomeDir)
|
||||
|
||||
entries, err := os.ReadDir(sitesDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gatherSiteNames: unable to read '%s'", sitesDir)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
siteName := entry.Name()
|
||||
if !slices.Contains(m.SiteNames, siteName) {
|
||||
m.SiteNames = append(m.SiteNames, siteName)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(m.SiteNames)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// PopulateOpenSiteMenu populates the open site menu with site names.
|
||||
func PopulateOpenSiteMenu(m *model.Model) error {
|
||||
menu, err := bldr.GetMenu(m.Builder, conf.OpenSiteMenu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var forEachErr error
|
||||
menu.GetChildren().Foreach(func(o interface{}) {
|
||||
menuItem, ok := o.(*gtk.Widget)
|
||||
if !ok {
|
||||
forEachErr = fmt.Errorf("PopulateOpenSiteMenu: unable to retrieve MenuItem")
|
||||
return
|
||||
}
|
||||
menu.Remove(menuItem)
|
||||
})
|
||||
if forEachErr != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := gatherSiteNames(m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for idx, siteName := range m.SiteNames {
|
||||
menuItem, err := gtk.MenuItemNew()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
menuItem.SetLabel(fmt.Sprintf("%d. %s", idx, siteName))
|
||||
menuItem.ShowAll()
|
||||
|
||||
menu.Append(menuItem)
|
||||
|
||||
menuItem.Connect("activate", func() {
|
||||
if err := OpenMenuChoice(m, menuItem); err != nil {
|
||||
if err := ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("PopulateOpenSiteMenu: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
155
internal/ui/init.go
Normal file
155
internal/ui/init.go
Normal file
@ -0,0 +1,155 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/codeclysm/extract"
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"varia.zone/hui/internal/conf"
|
||||
"varia.zone/hui/internal/model"
|
||||
)
|
||||
|
||||
// PostInitSpinner handles UI tasks after Hugo is downloaded.
|
||||
func PostInitSpinner(m *model.Model) error {
|
||||
if err := SwitchStackPage(m, conf.EmptyStackPage); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ShowSiteButtons(m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Initialise initialises the program.
|
||||
func Initialise(m *model.Model) error {
|
||||
msg := "Downloading Hugo... this could take a minute..."
|
||||
if err := SwitchStackPage(m, conf.BusyStackPage, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := initialise(m.User.HomeDir); err != nil {
|
||||
glib.IdleAdd(func() bool {
|
||||
if err := ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
if _, err := os.Stat(conf.HugoBinPath(m.User.HomeDir)); err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(1)
|
||||
}
|
||||
|
||||
glib.IdleAdd(func() bool {
|
||||
if err := PostInitSpinner(m); err != nil {
|
||||
if err := ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("main: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// initialise deals with initial setup functionality.
|
||||
func initialise(homeDir string) error {
|
||||
if err := createDirectories(homeDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := downloadHugo(homeDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// httpGetFile downloads a file from the internet.
|
||||
func httpGetFile(filepath, url string) error {
|
||||
out, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("httpGetFile: unable to create '%s': %s", filepath, err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("httpGetFile: unable to HTTP GET '%s'", url)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("httpGetFile: HTTP GET response code %v for '%s'", resp.StatusCode, url)
|
||||
}
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("httpGetFile: unable to copy HTTP GET response to disk: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// downloadHugo downloads Hugo.
|
||||
func downloadHugo(homeDir string) error {
|
||||
hugoTarPath := filepath.Join(conf.HugoDir(homeDir), fmt.Sprintf("hugo-%s.tar.gz", conf.HugoVersion))
|
||||
|
||||
if _, err := os.Stat(conf.HugoBinPath(homeDir)); err == nil {
|
||||
return nil
|
||||
} else if errors.Is(err, os.ErrNotExist) {
|
||||
if err := httpGetFile(hugoTarPath, conf.HugoReleaseURL); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fpath, err := ioutil.ReadFile(hugoTarPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("downloadHugo: unable to read file '%s': %s", hugoTarPath, err)
|
||||
}
|
||||
|
||||
if err := extract.Gz(context.TODO(), bytes.NewBuffer(fpath), conf.HugoDir(homeDir), nil); err != nil {
|
||||
return fmt.Errorf("downloadHugo: unable to extract file '%s': %s", hugoTarPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createDirectories creates all necessary application directories.
|
||||
func createDirectories(homeDir string) error {
|
||||
paths := []string{
|
||||
conf.DataDir(homeDir),
|
||||
conf.HugoDir(homeDir),
|
||||
conf.SitesDir(homeDir),
|
||||
}
|
||||
|
||||
for _, fpath := range paths {
|
||||
if _, err := os.Stat(fpath); err != nil && os.IsNotExist(err) {
|
||||
if err := os.Mkdir(fpath, 0764); err != nil {
|
||||
return fmt.Errorf("createDirectories: unable to create '%s': %s", fpath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
128
internal/ui/new.go
Normal file
128
internal/ui/new.go
Normal file
@ -0,0 +1,128 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"varia.zone/hui/internal/bldr"
|
||||
"varia.zone/hui/internal/conf"
|
||||
"varia.zone/hui/internal/model"
|
||||
)
|
||||
|
||||
// hugoNewSite creates a new Hugo site.
|
||||
func hugoNewSite(m *model.Model, siteName string) error {
|
||||
newSiteDir := conf.NewSiteDir(m.User.HomeDir, siteName)
|
||||
hugoBinPath := conf.HugoBinPath(m.User.HomeDir)
|
||||
|
||||
cmd := exec.Command(hugoBinPath, "new", "site", newSiteDir)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("unable to create new site: %s", err)
|
||||
}
|
||||
|
||||
// TODO(d1): allow users to choose a default theme
|
||||
if _, err := git.PlainClone(filepath.Join(newSiteDir, "themes", "nostyleplease"), false, &git.CloneOptions{
|
||||
URL: "https://github.com/g-hanwen/hugo-theme-nostyleplease",
|
||||
}); err != nil {
|
||||
return fmt.Errorf("unable to clone 'nostyleplease' theme: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShowNewSiteDialog shows the new site dialog.
|
||||
func ShowNewSiteDialog(m *model.Model) error {
|
||||
dialog, err := bldr.GetDialog(m.Builder, conf.NewSiteDialog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialog.Show()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HideNewSiteDialog hides the new site dialog.
|
||||
func HideNewSiteDialog(m *model.Model) error {
|
||||
dialog, err := bldr.GetDialog(m.Builder, conf.NewSiteDialog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialog.Hide()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateNewSite handles the creation of a new site.
|
||||
func CreateNewSite(m *model.Model) error {
|
||||
if err := HideNewSiteDialog(m); err != nil {
|
||||
return fmt.Errorf("CreateNewSite: %s", err)
|
||||
}
|
||||
|
||||
entry, err := bldr.GetEntry(m.Builder, conf.NewSiteNameEntry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CreateNewSite: %s", err)
|
||||
}
|
||||
|
||||
siteName, err := entry.GetText()
|
||||
if err != nil {
|
||||
return fmt.Errorf("CreateNewSite: %s", err)
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("Creating new site '%s'...", siteName)
|
||||
if err := SwitchStackPage(m, conf.BusyStackPage, msg); err != nil {
|
||||
return fmt.Errorf("CreateNewSite: %s", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := hugoNewSite(m, siteName); err != nil {
|
||||
glib.IdleAdd(func() bool {
|
||||
if err := ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("CreateNewSite: unable to show error dialog: %s", err))
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
glib.IdleAdd(func() bool {
|
||||
m.CurrentSite = siteName
|
||||
|
||||
if err := SetHeaderBarSubtitle(m, m.CurrentSite); err != nil {
|
||||
if err := ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("CreateNewSite: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
m.SiteNames = append(m.SiteNames, siteName)
|
||||
sort.Strings(m.SiteNames)
|
||||
|
||||
if err := PopulateOpenSiteMenu(m); err != nil {
|
||||
if err := ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("CreateNewSite: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
if err := SwitchStackPage(m, conf.ContentStackPage); err != nil {
|
||||
if err := ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("CreateNewSite: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
if err := ShowContentButtons(m); err != nil {
|
||||
if err := ShowErrDialog(m, err); err != nil {
|
||||
log.Fatal(fmt.Errorf("CreateNewSite: unable to show error dialog: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
34
internal/ui/preview.go
Normal file
34
internal/ui/preview.go
Normal file
@ -0,0 +1,34 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"varia.zone/hui/internal/model"
|
||||
)
|
||||
|
||||
func openLocalhost(url string) error {
|
||||
var cmd string
|
||||
var args []string
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
cmd = "open"
|
||||
default:
|
||||
cmd = "xdg-open"
|
||||
}
|
||||
|
||||
args = append(args, url)
|
||||
|
||||
return exec.Command(cmd, args...).Start()
|
||||
}
|
||||
|
||||
// PreviewSite previews the site locally.
|
||||
func PreviewSite(m *model.Model) error {
|
||||
// TODO: run serve with generated port
|
||||
// ensure no port clash by checking model
|
||||
|
||||
url := "http://localhost:1313"
|
||||
openLocalhost(url)
|
||||
return nil
|
||||
}
|
52
internal/ui/stack.go
Normal file
52
internal/ui/stack.go
Normal file
@ -0,0 +1,52 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"varia.zone/hui/internal/bldr"
|
||||
"varia.zone/hui/internal/conf"
|
||||
"varia.zone/hui/internal/model"
|
||||
)
|
||||
|
||||
var allStackPages = []string{
|
||||
conf.BusyStackPage,
|
||||
conf.ContentStackPage,
|
||||
conf.EmptyStackPage,
|
||||
conf.InitStackPage,
|
||||
}
|
||||
|
||||
// SwitchStackPage switches to a chosen stack page.
|
||||
func SwitchStackPage(m *model.Model, stackPageName string, args ...string) error {
|
||||
for _, spn := range allStackPages {
|
||||
stackPage, err := bldr.GetBox(m.Builder, spn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ShowStackPage: %s", err)
|
||||
}
|
||||
|
||||
if spn == stackPageName {
|
||||
stackPage.Show()
|
||||
|
||||
if spn == conf.BusyStackPage {
|
||||
if err := showBusyMessage(m, args...); err != nil {
|
||||
return fmt.Errorf("ShowStackPage: %s", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stackPage.Hide()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func showBusyMessage(m *model.Model, args ...string) error {
|
||||
label, err := bldr.GetLabel(m.Builder, conf.BusyStackLabel)
|
||||
if err != nil {
|
||||
return fmt.Errorf("showBusyMessage: %s", err)
|
||||
}
|
||||
|
||||
msg := args[0]
|
||||
label.SetLabel(msg)
|
||||
|
||||
return nil
|
||||
}
|
14
makefile
Normal file
14
makefile
Normal file
@ -0,0 +1,14 @@
|
||||
HUI := ./cmd/hui
|
||||
BUILD_FLAGS := "-v"
|
||||
LD_FLAGS := -ldflags="-s -w"
|
||||
|
||||
default: run
|
||||
|
||||
build:
|
||||
@go build $(BUILD_FLAGS) $(LD_FLAGS) $(HUI)
|
||||
|
||||
update:
|
||||
@go get -u ./... && go mod tidy
|
||||
|
||||
run:
|
||||
@go run $(LD_FLAGS) $(HUI)
|
705
ui/hui.glade
Normal file
705
ui/hui.glade
Normal file
@ -0,0 +1,705 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.40.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkDialog" id="errorDialog">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="type-hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-left">8</property>
|
||||
<property name="margin-right">8</property>
|
||||
<property name="margin-start">8</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="layout-style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="errorCloseButton">
|
||||
<property name="label" translatable="yes">Close</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<signal name="clicked" handler="hideErrorDialog" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="errorBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-left">8</property>
|
||||
<property name="margin-right">8</property>
|
||||
<property name="margin-start">8</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="errorStatusLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Something went wrong 🙈</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="size" value="10000"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="errorMessageLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="existingSiteDialog">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="type-hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="existingSiteBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-left">8</property>
|
||||
<property name="margin-right">8</property>
|
||||
<property name="margin-start">8</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="existingSiteButtonBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="layout-style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="cancelexistingSiteButton">
|
||||
<property name="label" translatable="yes">Cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-top">5</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="existingSiteFromGitUrlLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Existing site from Git URL</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="existingSiteGitUrlEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="margin-left">2</property>
|
||||
<property name="margin-right">2</property>
|
||||
<property name="margin-start">2</property>
|
||||
<property name="margin-end">2</property>
|
||||
<property name="margin-top">2</property>
|
||||
<property name="margin-bottom">2</property>
|
||||
<property name="primary-icon-name">accessories-text-editor</property>
|
||||
<property name="placeholder-text" translatable="yes">ssh://git@example.org:foo.git</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="existingSiteFromGitUrlBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="existingSiteFromGitUrlButton">
|
||||
<property name="label" translatable="yes">Clone</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-top">5</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="existingSiteFromFSLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Existing site from the File system</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="existingSiteFromFSComboxBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox" id="existingSiteFromFSButtonBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="layout-style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="existingSiteFromFSButton">
|
||||
<property name="label" translatable="yes">Select</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkMenu" id="openSiteMenu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="mainWindow">
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkStack" id="mainWindowStack">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="add" handler="initStackPageShow" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkBox" id="initStackPage">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="initWelcomeLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="label" translatable="yes">Welcome to Hughie 🎉</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="size" value="30000"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="initPromptBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="initPromptLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="label" translatable="yes">It looks like this is your first time here. We need to download Hugo and set up the file system. Click "Setup" to get started</property>
|
||||
<property name="justify">center</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="max-width-chars">50</property>
|
||||
<attributes>
|
||||
<attribute name="size" value="11000"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="initPromptButton">
|
||||
<property name="label" translatable="yes">Setup</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-left">5</property>
|
||||
<property name="margin-top">10</property>
|
||||
<signal name="clicked" handler="initialise" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">initStackPage</property>
|
||||
<property name="title" translatable="yes">initStackPage</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="emptyStackPage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="contentStackPageBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="contentStackPagePlaceholderLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Open or create a new site to get started</property>
|
||||
<attributes>
|
||||
<attribute name="size" value="15000"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">contentStackPage</property>
|
||||
<property name="title" translatable="yes">contentStackPage</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="busyStackPage">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="busyStackBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="busyStackLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinner" id="busyStackSpinner">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">page0</property>
|
||||
<property name="title" translatable="yes">page0</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="contentStackPage">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="label" translatable="yes">TODO: implement</property>
|
||||
<attributes>
|
||||
<attribute name="size" value="20000"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">page1</property>
|
||||
<property name="title" translatable="yes">page1</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerBar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="title" translatable="yes">Hughie</property>
|
||||
<property name="spacing">0</property>
|
||||
<property name="show-close-button">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="openSiteBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="tooltip-text" translatable="yes">Open an existing site</property>
|
||||
<property name="margin-right">5</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="openSiteButton">
|
||||
<property name="label" translatable="yes">Open</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="openSiteSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="openSiteMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="popup">openSiteMenu</property>
|
||||
<property name="use-popover">False</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="openSiteMenuIcon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">pan-down-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="createSiteButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Create new site</property>
|
||||
<property name="margin-right">5</property>
|
||||
<signal name="clicked" handler="showNewSiteDialog" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="createSiteButtonIcon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">document-new-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="headerBarSeparator">
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="createPostButton">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Create new post</property>
|
||||
<property name="margin-left">5</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="createPostButtonIcon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">text-editor</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="previewButton">
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Preview site in browser</property>
|
||||
<property name="margin-left">5</property>
|
||||
<signal name="clicked" handler="previewSite" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="previewButtonIcon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">view-reveal-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="primaryMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-right">15</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="primaryMenuButtonIcon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="newSiteDialog">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="window-position">center</property>
|
||||
<property name="type-hint">dialog</property>
|
||||
<property name="gravity">center</property>
|
||||
<property name="transient-for">mainWindow</property>
|
||||
<property name="attached-to">mainWindow</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="newSiteBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-left">8</property>
|
||||
<property name="margin-right">8</property>
|
||||
<property name="margin-start">8</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="newSiteButtonBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="layout-style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="cancelCreateSiteButton">
|
||||
<property name="label" translatable="yes">Cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-top">5</property>
|
||||
<signal name="clicked" handler="hideNewSiteDialog" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="createSiteButton2">
|
||||
<property name="label" translatable="yes">Create</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-top">5</property>
|
||||
<signal name="clicked" handler="createNewSite" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="newSiteNameLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">New site name</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="newSiteNameEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="margin-left">2</property>
|
||||
<property name="margin-right">2</property>
|
||||
<property name="margin-start">2</property>
|
||||
<property name="margin-end">2</property>
|
||||
<property name="margin-top">2</property>
|
||||
<property name="margin-bottom">2</property>
|
||||
<property name="primary-icon-name">accessories-text-editor</property>
|
||||
<property name="placeholder-text" translatable="yes">another.varia.zone</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
Reference in New Issue
Block a user