// New creates an applet preview widget. // func New(log cdtype.Logger) *Preview { builder := buildhelp.New() builder.AddFromString(string(appletpreviewXML())) // builder.AddFromFile("appletpreview.xml") widget := &Preview{ Box: *builder.GetBox("widget"), title: builder.GetLabel("title"), author: builder.GetLabel("author"), size: builder.GetLabel("size"), stateText: builder.GetLabel("stateText"), stateIcon: builder.GetImage("stateIcon"), description: builder.GetLabel("description"), previewFrame: builder.GetFrame("previewFrame"), previewImage: builder.GetImage("previewImage"), log: log, } if len(builder.Errors) > 0 { for _, e := range builder.Errors { log.Err(e, "build appletpreview") } return nil } widget.Connect("destroy", widget.RemoveTmpFile) return widget }
// NewFromFileSafe creates a config page builder from the file. // // If the load file failed, an error widget is returned with false. // func NewFromFileSafe(source cftype.Source, log cdtype.Logger, file, originalConf, gettextDomain string) (cftype.Grouper, bool) { build, e := NewFromFile(source, log, file, originalConf, gettextDomain) if !log.Err(e, "Load config file", file) { return build, true // Load ok, return it. } // Load failed. Build a warning widget from virtual source. conf := vstorage.NewVirtual(file, originalConf) build = newFromStorage(source, log, conf, originalConf, gettextDomain) group := "problem" build.AddGroup(group, newkey.Frame(group, "fail", "Load failed", "dialog-error"), newkey.TextLabel(group, "text", "Can't load the configuration file to build the interface."), newkey.TextLabel(group, "file", file), ) hack := TweakKeyMakeWidget(group, "file", func(key *cftype.Key) { key.Label().SetLineWrap(true) // key.Label().SetJustify(gtk.JUSTIFY_FILL) key.Label().SetSelectable(true) }) return build.BuildSingle(group, hack), false }
// New creates a dock shortkeys management widget. // func New(control cftype.Source, log cdtype.Logger, btn btnaction.Tune) *Shortkeys { builder := buildhelp.NewFromBytes(confshortkeysXML()) widget := &Shortkeys{ ScrolledWindow: *builder.GetScrolledWindow("widget"), model: builder.GetListStore("model"), tree: builder.GetTreeView("tree"), selection: builder.GetTreeSelection("selection"), control: control, btn: btn, log: log, rows: make(map[*gtk.TreeIter]cdglobal.Shortkeyer), } rend := builder.GetCellRendererText("cellrenderertextShortkey") if len(builder.Errors) > 0 { for _, e := range builder.Errors { log.Err(e, "build confshortkeys") } return nil } // The user is allowed to edit the shortcut text. This will handle the new text. rend.Connect("edited", widget.onManualEdit) widget.Load() return widget }
// NewList creates cairo-dock main config pages list. // func NewList(control controlItems, log cdtype.Logger) *List { builder := buildhelp.NewFromBytes(confcoreXML()) widget := &List{ ScrolledWindow: *builder.GetScrolledWindow("widget"), model: builder.GetListStore("model"), tree: builder.GetTreeView("tree"), selection: builder.GetTreeSelection("selection"), control: control, log: log, rows: make(map[string]*row), } if len(builder.Errors) > 0 { for _, e := range builder.Errors { log.Err(e, "build confcore list") } return nil } // Action: Treeview Select line. widget.selection.Connect("changed", widget.onSelectionChanged) return widget }
func getValueListCombo(widget *gtk.ComboBox, model *gtk.ListStore, log cdtype.Logger) func() interface{} { return func() interface{} { iter, _ := widget.GetActiveIter() text, e := getActiveRowInCombo(model, iter) log.Err(e, "ListIcons") return text } }
// InfoApplet asks the dock all informations about an applet. // func InfoApplet(log cdtype.Logger, name string) *packages.AppletPackage { vars, _ := DockProperties("type=Module & name=" + name) if len(vars) == 0 { log.NewErr("unknown applet", "InfoApplet", name) return nil } pack, _ := parseApplet(log, vars[0]) return pack }
// ListFieldsIDByName searches the list of fields for the matching key. // Returns the position of the field in the list. // Returns 0 if not found, to have a valid entry to select. // func ListFieldsIDByName(fields []Field, key string, log cdtype.Logger) int { for i, field := range fields { if key == field.Key { return i } } if log != nil { log.NewErr("not found", "ListFieldsIDByName", key, fields) } return 0 }
// NewYTDLFile creates a video file downloader. // func NewYTDLFile(log cdtype.Logger, url string) (Filer, error) { info, e := ytdl.GetVideoInfo(url) if e != nil { return nil, fmt.Errorf("Unable to fetch video info: %s", e.Error()) } // formats := info.Formats // // parse filter arguments, and filter through formats // for _, filter := range options.filters { // filter, e := parseFilter(filter) // if !log.Err(e) { // formats = filter(formats) // } // } // if len(formats) == 0 { // return nil, fmt.Errorf("No formats available that match criteria: %s", e.Error()) // } log.Info("Author", info.Author) log.Info("Description", info.Description) log.Info("ID", info.ID) log.Info("vid", info) var list []*Format for _, v := range info.Formats { nf := &Format{ Itag: v.Itag, Extension: v.Extension, Resolution: v.Resolution, VideoEncoding: v.VideoEncoding, AudioEncoding: v.AudioEncoding, AudioBitrate: v.AudioBitrate, } s := v.ValueForKey("clen") if s != nil { nf.Size, e = strconv.Atoi(s.(string)) nf.Size /= 1000000 log.Err(e, "convert size. format=", v.Itag) // } else { // log.Info("no clen", v.Itag) } list = append(list, nf) } // pretty.Println(info) return &YTDLFile{ VideoInfo: *info, formats: list, log: log, }, nil }
// New creates a welcome widget with informations about the program. // func New(source cftype.Source, log cdtype.Logger, switcher *pageswitch.Switcher) cftype.Grouper { const group = "Dev" title := tran.Slate("hi") // all packages in the application gopath. pathGoTest := strings.Join(append(cdglobal.AppBuildPath, "..."), "/") pathTestConfCmd := cdglobal.AppBuildPathFull("test", "confcmd", "confcmd.go") pathTestConfGUI := cdglobal.AppBuildPathFull("test", "confgui", "confgui.go") pathTestConfCmd, _ = filepath.EvalSymlinks(pathTestConfCmd) pathTestConfGUI, _ = filepath.EvalSymlinks(pathTestConfGUI) printConfig := func(showAll bool) { path := source.MainConfigFile() def := source.MainConfigDefault() otherSw := pageswitch.New() defer otherSw.Destroy() build, e := cfbuild.NewFromFile(source, log, path, def, "") if !log.Err(e, "load current dock config file") { // build.BuildSingle("TaskBar") build.BuildAll(otherSw) println("conf", path, def) cfprint.Default(build, showAll) build.Destroy() } } buildInfo := cfbuild.TweakAddGroup(group, newkey.TextLabel(group, "txt_title", common.Bold(common.Big(title))), newkey.Separator(group, "sep_title"), newkey.TextLabel(group, "txt_dev_page", "Test page, with useful tools for the developer."), newkey.CustomButtonLabel(group, "printConfig", "Print configuration", "show mainconf edited", func() { printConfig(false) }), newkey.CustomButtonLabel(group, "printConfig", "Print configuration", "show mainconf all", func() { printConfig(true) }), newkey.Separator(group, "sep_go_area"), newkey.TextLabel(group, "txt_go_area", "<b>Those commands requires the application sources in their Go environment</b>."), newkey.Separator(group, "sep_tests_gui"), newkey.LaunchCommand(group, "testConfGUI", "Launch config GUI test", "go run "+pathTestConfGUI), newkey.Separator(group, "sep_tests_cmd"), newkey.LaunchCommand(group, "testConfGUI", "Launch config console test", "go run "+pathTestConfCmd), newkey.LaunchCommand(group, "testConfGUI", "Launch config console mainconf diff", "go run "+pathTestConfCmd+" "+source.MainConfigFile()), newkey.Separator(group, "sep_tests_go"), newkey.LaunchCommand(group, "gotest", "Launch go tests", "go test "+pathGoTest), newkey.LaunchCommand(group, "golint", "Launch go lint", "golint "+pathGoTest), newkey.LaunchCommand(group, "govet", "Launch go vet", "go vet "+pathGoTest), ) build := cfbuild.NewVirtual(source, log, "", "", "").BuildAll(switcher, buildInfo) build.ShowAll() return build }
// NewServer creates a Dbus service. // func NewServer(srvObj, srvPath string, log cdtype.Logger) *Server { conn, c, e := SessionBus() if log.Err(e, "DBus Connect") { return nil } load := &Server{ Conn: conn, Events: c, Log: log, srvObj: srvObj, srvPath: srvPath, } return load }
// NewBuilder creates the target renderer/builder. // The name is mandatory for a single applet (internal or not). // func NewBuilder(target SourceType, name string, log cdtype.Logger) Builder { switch target { case TypeGodock: build := &BuilderGodock{} build.SetLogger(log) return build case TypeCore: build := &BuilderCore{} build.SetLogger(log) return build case TypeApplets: build := &BuilderApplets{} build.SetLogger(log) return build case TypeAppletCompiled: dir, icon := AppletInfo(log, name) if dir == "" { log.NewErr("applet not found: "+name, "new builder") return &BuilderNull{} } build := &BuilderCompiled{Module: name} build.SetLogger(log) build.SetIcon(icon) build.SetDir(dir) return build case TypeAppletInternal: // Ask icon of module to the Dock as we can't guess its dir and icon name. _, icon := AppletInfo(log, strings.Replace(name, "-", " ", -1)) if icon == "" { icon = IconMissing } build := &BuilderInternal{Module: name} build.SetLogger(log) build.SetIcon(icon) return build } // ensure we have a valid target. return &BuilderNull{} }
// NewFromFile creates a config page builder from the file. // func NewFromFile(source cftype.Source, log cdtype.Logger, configFile, originalConf, gettextDomain string) (cftype.Grouper, error) { storage, e := LoadFile(configFile, originalConf) if e != nil { log.Err(e, "NewFromFile") return nil, e } grouper := newFromStorage(source, log, storage, originalConf, gettextDomain) grouper.free = func() { grouper.keyFile = &storage.KeyFile // MOVE ONE LINE UP ? grouper.Builder.Free() storage.KeyFile.Free() if storage.def != nil { storage.def.Free() } } return grouper, nil }
// ListIcons asks the dock the list of active icons. // // TODO: add argument for advanced queries. // would be cool to have argument list. // func ListIcons(log cdtype.Logger) (list []*CDIcon) { iconsInfo, e := DockProperties("type=Icon") log.Err(e, "ListIcons") for _, props := range iconsInfo { ic := &CDIcon{log: log} for k, v := range props { ic.getProp(k, v) } // if ic.Name == "" { // log.NewErr("ListIcons name empty", ic.Type, ic.ConfigFile) // } else { list = append(list, ic) // } } return }
// NewList creates a new applets list widget. // func NewList(control ControlDownload, log cdtype.Logger) *List { builder := buildhelp.New() builder.AddFromString(string(appletlistXML())) // builder.AddFromFile("appletlist.xml") widget := &List{ ScrolledWindow: *builder.GetScrolledWindow("widget"), model: builder.GetListStore("model"), tree: builder.GetTreeView("tree"), columnCategory: builder.GetTreeViewColumn("columnCategory"), control: control, log: log, rows: make(map[string]*Row), } columnName := builder.GetTreeViewColumn("columnName") if len(builder.Errors) > 0 { for _, e := range builder.Errors { log.Err(e, "build appletlist") } return nil } control.SetControlInstall(widget) // Double click launch add action. widget.tree.Connect("button-press-event", func(tree *gtk.TreeView, ev *gdk.Event) { btn := &gdk.EventButton{Event: ev} if btn.Button() == 1 && btn.Type() == gdk.EVENT_2BUTTON_PRESS { control.Save() } }) // Action: Treeview Select line. if sel, e := widget.tree.GetSelection(); !log.Err(e, "appletlist TreeView.GetSelection") { sel.Connect("changed", widget.onSelectionChanged) // Changed is connected to TreeSelection } // Sort applets by name. columnName.Emit("clicked") return widget }
// Run starts dock routines and locks the main thread with gtk. // // It wraps all backends and clients to start a dock : // Dbus server, applets manager, GUI, menu and gldi. // // Dbus service is enabled by default. Mandatory if enabled, to provide remote control. // This will prevent launching a 2nd instance without the disable Dbus service option. // // You can add custom changes, launched before the start, with CustomHacks. // // Run returns true if the dock is able to start. This can be done with: // gldi.Lock() // alias for gtk_main. // maindock.Clean() // may be better with defer, but cause confused panic messages. // func Run(log cdtype.Logger, getSettings func() maindock.DockSettings) bool { settings := getSettings() // Logger debug state. log.SetDebug(settings.Debug) maindock.SetLogger(log) // Dock init. settings.Init() // Load new config settings. New options are in an other file to keep the // original config file as compatible with the real dock as possible. file, e := globals.DirUserAppData(confown.GuiFilename) e = confown.Init(log, file, e) log.Err(e, "Load ConfigSettings") // Register go internal applets events. appmgr := mgrgldi.Register(log) // Start the polling loop for go internal applets (can be in DBus with other events). if settings.DisableDBus { go appmgr.StartLoop() } else { // DBus service is mandatory if enabled. This prevent double launch. dbus, e := serviceDbus(log) if log.Err(e, "start dbus service") { fmt.Println("restart the program with the -N flag if you really need a second instance") return false } dbus.SetManager(appmgr) go dbus.StartLoop() } // HTTP listener for the pprof debug. if settings.HTTPPprof { websrv.Service.Register("debug/pprof", pprof.Index, log) websrv.Service.Start("debug/pprof") } // Print useful packages versions. versions.Print() // Custom calls added by devs for their own uses and tests. CustomHacks() // Register GUI events. backendgui.Register(guibridge.New(log)) // Register mouse events. eventmouse.Register(log) // Register menus events. backendmenu.Register(log, mainmenu.BuildMenuContainer, mainmenu.BuildMenuIcon) // Finish startup. settings.Start() return true }
// Init will try to load the own config data from the file, and create it if missing. // func Init(log cdtype.Logger, file string, e error) error { if e != nil { return e } // Create file if needed. if !files.IsExist(file) { source := globals.DirShareData(GuiFilename) e := files.CopyFile(source, file, os.FileMode(0644)) if e != nil { return e } log.Info("created config file", file) } // Create our user settings Settings = ConfigSettings{ File: file, log: log, } return Settings.Load() }
// NewMenuDownload creates the menu to control the selected applet. // func NewMenuDownload(log cdtype.Logger) *MenuDownload { widget := &MenuDownload{ Box: *newgtk.Box(gtk.ORIENTATION_HORIZONTAL, 0), installed: newgtk.Switch(), active: newgtk.Switch(), log: log, } // Actions var e error widget.handlerInstalled, e = widget.installed.Connect("notify::active", widget.toggledInstalled) log.Err(e, "Connect installed button callback") widget.handlerActive, e = widget.active.Connect("notify::active", widget.toggledActive) log.Err(e, "Connect active button callback") widget.PackStart(newgtk.Label("Installed"), false, false, 4) widget.PackStart(widget.installed, false, false, 0) widget.PackStart(newgtk.Box(gtk.ORIENTATION_VERTICAL, 0), false, false, 8) widget.PackStart(newgtk.Label("Active"), false, false, 4) widget.PackStart(widget.active, false, false, 0) return widget }
func (o *dockIcon) LaunchCommand(log cdtype.Logger, args ...string) bool { cmd := o.GetCommand() switch { case cmd == "": case cmd[0] == '<': // Launch as shortkey. success := shortkeys.Trigger(cmd) if success { return true } // try also as exec. exec, e := log.ExecShlex(cmd, args...) if log.Err(e, "parse command", cmd) { return false } e = exec.Run() return e == nil default: // Exec command. exec, e := log.ExecShlex(cmd, args...) if log.Err(e, "parse command", cmd) { return false } e = exec.Run() if log.Err(e, "launch command", cmd, strings.Join(args, " ")) { // try also as shortkey. return shortkeys.Trigger(cmd) } return true } return false }
// New creates a handbook widget (applet info). // func New(log cdtype.Logger) *Handbook { builder := buildhelp.New() builder.AddFromString(string(handbookXML())) // builder.AddFromFile("handbook.xml") widget := &Handbook{ Frame: *builder.GetFrame("handbook"), title: builder.GetLabel("title"), author: builder.GetLabel("author"), description: builder.GetLabel("description"), previewFrame: builder.GetFrame("previewFrame"), previewImage: builder.GetImage("previewImage"), } if len(builder.Errors) > 0 { for _, e := range builder.Errors { log.Err(e, "build handbook") } return nil } return widget }
// AccessUnlock releases the access to config files. // func AccessUnlock(log cdtype.Logger) { log.Debug("files.Access", "Unlock") access.Unlock() }
// AccessLock locks and prevents concurrent access to config files. // Could be improved, but it may be safer to use for now. // func AccessLock(log cdtype.Logger) { log.Debug("files.Access", "Lock") access.Lock() }