func (g *GUI) mkMenuBar() *gtk.MenuBar { menubar := gtk.NewMenuBar() fileMenu := gtk.NewMenu() open := gtk.NewImageMenuItemFromStock(gtk.STOCK_OPEN, g.accel) open.Connect("activate", g.openWorldDlg) fileMenu.Append(open) if quickopen, ok := g.mkQuickOpen(); ok { quickopenItem := gtk.NewMenuItemWithLabel("Open Map") quickopenItem.SetSubmenu(quickopen) fileMenu.Append(quickopenItem) } g.menuitemSave = gtk.NewImageMenuItemFromStock(gtk.STOCK_SAVE, g.accel) g.menuitemSave.Connect("activate", g.save) g.menuitemSave.SetSensitive(false) fileMenu.Append(g.menuitemSave) quit := gtk.NewImageMenuItemFromStock(gtk.STOCK_QUIT, g.accel) quit.Connect("activate", g.exitApp) fileMenu.Append(quit) fileMenuItem := gtk.NewMenuItemWithLabel("File") fileMenuItem.SetSubmenu(fileMenu) menubar.Append(fileMenuItem) helpMenu := gtk.NewMenu() controls := gtk.NewMenuItemWithLabel("Controls") controls.Connect("activate", func() { dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Click to use selected tool.\nMiddle mouse button to move around.") dlg.Run() dlg.Destroy() }) helpMenu.Append(controls) about := gtk.NewImageMenuItemFromStock(gtk.STOCK_ABOUT, g.accel) about.Connect("activate", g.aboutDlg) helpMenu.Append(about) helpMenuItem := gtk.NewMenuItemWithLabel("Help") helpMenuItem.SetSubmenu(helpMenu) menubar.Append(helpMenuItem) return menubar }
func main() { gtk.Init(&os.Args) glib.SetApplicationName("go-gtk-statusicon-example") mi := gtk.NewMenuItemWithLabel("Popup!") mi.Connect("activate", func() { gtk.MainQuit() }) nm := gtk.NewMenu() nm.Append(mi) nm.ShowAll() si := gtk.NewStatusIconFromStock(gtk.STOCK_FILE) si.SetTitle("StatusIcon Example") si.SetTooltipMarkup("StatusIcon Example") si.Connect("popup-menu", func(cbx *glib.CallbackContext) { nm.Popup(nil, nil, gtk.StatusIconPositionMenu, si, uint(cbx.Args(0)), uint(cbx.Args(1))) }) println(` Can you see statusicon in systray? If you don't see it and if you use 'unity', try following. # gsettings set com.canonical.Unity.Panel systray-whitelist \ "$(gsettings get com.canonical.Unity.Panel systray-whitelist \| sed -e "s/]$/, 'go-gtk-statusicon-example']/")" `) gtk.Main() }
func (g *GUI) mkQuickOpen() (*gtk.Menu, bool) { maps := allMaps() if (maps == nil) || (len(maps) == 0) { return nil, false } menu := gtk.NewMenu() for name, p := range maps { mitem := gtk.NewMenuItemWithLabel(name) p2 := p mitem.Connect("activate", func() { g.openWorld(p2) }) menu.Append(mitem) } return menu, true }
// newMenuFromItems returns a GTK menu from a pathtree.Items map. This function // calls itself recursively and takes a relpath used to build the absolute path // needed by the pass command. func newMenuFromItems(items pathtree.Items, relpath string) *gtk.Menu { result := gtk.NewMenu() for k, v := range items { mi := gtk.NewMenuItemWithLabel(k) abspath := relpath + k if len(v) > 0 { mi.SetSubmenu(newMenuFromItems(v, abspath+"/")) } else { mi.Connect("activate", func() { exec.Command("pass", abspath, "-c").Run() }) } result.Append(mi) } return result }
// main reads the config file, connects to each IMAP server in a separate thread // and watches the notify channel for messages telling it to update the status // icon. func main() { conf, err := goconf.ReadConfigFile(os.Getenv("HOME") + "/.hasmailrc") if err != nil { fmt.Println("Failed to load configuration file, exiting...\n", err) return } // This channel will be used to tell us if we should exit the program quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) // GTK engage! gtk.Init(&os.Args) glib.SetApplicationName("hasmail") defer gtk.MainQuit() // Set up the tray icon si := gtk.NewStatusIconFromStock(gtk.STOCK_DISCONNECT) si.SetTitle("hasmail") si.SetTooltipMarkup("Not connected") // Set up the tray icon right click menu mi := gtk.NewMenuItemWithLabel("Quit") mi.Connect("activate", func() { quit <- syscall.SIGINT }) nm := gtk.NewMenu() nm.Append(mi) nm.ShowAll() si.Connect("popup-menu", func(cbx *glib.CallbackContext) { nm.Popup(nil, nil, gtk.StatusIconPositionMenu, si, uint(cbx.Args(0)), uint32(cbx.Args(1))) }) /* If the user clicks the tray icon, here's what happens: * - if only a single account has new emails, and a click command has been * specified for that account, execute it * - if the user has specified a default click handler, execute that * - otherwise, do nothing */ si.Connect("activate", func(cbx *glib.CallbackContext) { command, geterr := conf.GetString("default", "click") nonZero := 0 nonZeroAccount := "" for account, unseenList := range parts.Unseen { if len(unseenList) > 0 { nonZero++ nonZeroAccount = account } } // Can't just use HasOption here because that also checks "default" section, // even though Get* doesn't... if nonZero == 1 { acommand, ageterr := conf.GetString(nonZeroAccount, "click") if ageterr == nil { command = acommand geterr = ageterr } } if geterr == nil { fmt.Printf("Executing user command: %s\n", command) shell := os.Getenv("SHELL") if shell == "" { shell = "/bin/sh" } sh := exec.Command(shell, "-c", command) sh.Env = os.Environ() err = sh.Start() if err != nil { fmt.Printf("Failed to run command '%s' on click\n", command) fmt.Println(err) } } else { fmt.Println("No action defined for click\n", geterr) } }) go gtk.Main() // Connect to all accounts sections := conf.GetSections() notify := make(chan bool, len(sections)) for _, account := range sections { // default isn't really an account if account == "default" { continue } initConnection(notify, conf, account) } // Let the user know that we've now initiated all the connections si.SetFromStock(gtk.STOCK_CONNECT) si.SetTooltipText("Connecting") // Keep updating the status icon (or quit if the user wants us to) for { select { case <-quit: return case <-notify: totUnseen := 0 s := "" for account, e := range parts.Errs { if e == 0 { continue } s += account + ": " switch e { case 1: s += "Connection failed!" case 2: s += "IDLE not supported!" case 3: s += "No login credentials given!" case 4: s += "Login failed!" case 5: s += "Connection dropped!" } s += "\n" } for account, unseenList := range parts.Unseen { if parts.Errs[account] != 0 { continue } numUnseen := len(unseenList) if numUnseen >= 0 { totUnseen += numUnseen } s += account + ": " switch numUnseen { case 0: s += "No new messages" case 1: s += "One new message" default: s += fmt.Sprintf("%d new messages", numUnseen) } s += "\n" } // get rid of trailing newline s = strings.TrimRight(s, "\n") si.SetTooltipText(s) // http://developer.gnome.org/gtk3/3.0/gtk3-Stock-Items.html switch totUnseen { case 0: si.SetFromStock(gtk.STOCK_NEW) case 1: si.SetFromStock(gtk.STOCK_DND) default: si.SetFromStock(gtk.STOCK_DND_MULTIPLE) } } } }
func main() { flag.Parse() usr, err := user.Current() if err != nil { fmt.Println("Couldn't get home directory:", err) return } file, err := ioutil.ReadFile(usr.HomeDir + "/.gpuush") if err != nil { fmt.Println("Config file error:", err) return } err = json.Unmarshal(file, &conf) if err != nil { fmt.Println("Config file error:", err) return } success := login(conf.Email, conf.Pass) if !success { return } if background { quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) gtk.Init(&os.Args) glib.SetApplicationName("gpuush") defer gtk.MainQuit() si := gtk.NewStatusIconFromFile("/usr/local/share/gpuush/icon.png") si.SetTitle("gpuush") si.SetTooltipMarkup("gpuush") nm := gtk.NewMenu() mi := gtk.NewMenuItemWithLabel("Take Screenshot") mi.Connect("activate", func() { go takeScreenshot() }) nm.Append(mi) nm.ShowAll() mi = gtk.NewMenuItemWithLabel("Quit") mi.Connect("activate", func() { quit <- syscall.SIGINT }) nm.Append(mi) nm.ShowAll() si.Connect("popup-menu", func(cbx *glib.CallbackContext) { nm.Popup(nil, nil, gtk.StatusIconPositionMenu, si, uint(cbx.Args(0)), uint32(cbx.Args(1))) }) go gtk.Main() for { select { case <-quit: return } } } else if screenshot { takeScreenshot() } else { result := uploadFile(flag.Arg(0)) if len(result) > 0 { notify(result) copy(result) } else { notify("Upload failed") } } }