Esempio n. 1
0
// SetDefaults set basic defaults icon settings in one call.
// Empty fields will be reset, so this is better used in the Init() call.
//
func (cda *CDApplet) SetDefaults(def cdtype.Defaults) {
	// Apply defaults.
	cda.SetIcon(ternary.String(def.Icon != "", def.Icon, cda.FileLocation("icon")))
	cda.SetLabel(ternary.String(def.Label != "", def.Label, cda.Name()))
	cda.SetQuickInfo(def.QuickInfo)

	cda.shortkeys = def.Shortkeys
	for _, sk := range cda.shortkeys {
		switch {
		case sk.ActionID <= 0:

		case sk.ActionID >= cda.Action().Len():
			cda.Log().NewWarn("action not defined", "shortkey: ", sk.ConfGroup, sk.Shortkey) // sk.ActionID

		default:
			sk.Call = cda.Action().Callback(sk.ActionID)
		}
	}
	cda.BindShortkey(cda.shortkeys...)

	cda.Command().Clear()
	for key, cmd := range def.Commands {
		cda.Command().Add(key, cmd)
	}
	cda.Window().SetAppliClass(cda.Command().FindMonitor())

	if cda.Poller().Exists() {
		cda.Poller().SetInterval(def.PollerInterval)
	}

	cda.log.SetDebug(def.Debug)
}
Esempio n. 2
0
// AddButtonsEntry adds an item with button entries to the menu.
//
func (m *DockMenu) AddButtonsEntry(label string, btns ...MenuBtn) *menus.ButtonsEntry {
	entry := m.Menu.AddButtonsEntry(label)

	for _, btnID := range btns {
		switch btnID {
		case MenuWindowClose:
			entry.AddButton(
				tran.Slate("Close")+actionMiddleClick(m.Icon, 1),
				globals.DirShareData("icons", "icon-close.svg"),
				m.Icon.CallbackActionWindow((cdglobal.Window).Close))

		case MenuWindowCloseAll:
			entry.AddButton(
				tran.Slate("Close all")+actionMiddleClick(m.Icon, 1),
				globals.DirShareData("icons", "icon-close.svg"),
				m.Icon.CallbackActionSubWindows((cdglobal.Window).Close))

		case MenuWindowMax:
			max := m.Icon.Window().IsMaximized()
			entry.AddButton(
				ternary.String(max, tran.Slate("Unmaximise"), tran.Slate("Maximise")),
				globals.DirShareData("icons", ternary.String(max, "icon-restore.svg", "icon-maximize.svg")),
				m.Icon.CallbackActionWindowToggle((cdglobal.Window).Maximize, (cdglobal.Window).IsMaximized))

		case MenuWindowMin:
			entry.AddButton(
				tran.Slate("Minimise")+actionMiddleClick(m.Icon, 2),
				globals.DirShareData("icons", "icon-minimize.svg"),
				m.Icon.CallbackActionWindow((cdglobal.Window).Minimize))

		case MenuWindowMinAll:
			entry.AddButton(
				tran.Slate("Minimise all")+actionMiddleClick(m.Icon, 2),
				globals.DirShareData("icons", "icon-minimize.svg"),
				m.Icon.CallbackActionSubWindows((cdglobal.Window).Minimize))

		case MenuWindowShow:
			entry.AddButton(
				tran.Slate("Show"),
				globals.IconNameFind,
				m.Icon.CallbackActionWindow((cdglobal.Window).Show))

		case MenuWindowShowAll:
			entry.AddButton(
				tran.Slate("Show all"),
				globals.IconNameFind,
				m.Icon.CallbackActionSubWindows((cdglobal.Window).Show))

		default:
			log.NewWarn(fmt.Sprintf("invalid id: %d", btnID), "AddButtonsEntry")
		}
	}
	return entry
}
Esempio n. 3
0
func init() {
	Name = "Custom Dock"

	List = append(List,
		Field{"  gldi     ", globals.Version()},
		Field{"  OpenGL   ", ternary.String(gldi.GLBackendIsUsed(), "Yes", "No")},
	)
}
Esempio n. 4
0
// ListViews returns the list of views.
//
func (Data) ListViews() map[string]datatype.Handbooker {
	list := make(map[string]datatype.Handbooker)
	for key, rend := range docklist.CairoDockRenderer() {
		list[key] = &HandbookDescTranslate{&datatype.HandbookDescDisk{Handbooker: &datatype.HandbookSimple{
			Key:         key,
			Title:       ternary.String(rend.GetDisplayedName() != "", rend.GetDisplayedName(), key),
			Description: rend.GetReadmeFilePath(),
			Preview:     rend.GetPreviewFilePath(),
		}}}
	}
	return list
}
Esempio n. 5
0
// Request login informations from user. Popup an AskText dialog.
// Save to disk and try to get new data if confirmed.
//
func (app *Applet) actionRegister() {
	text := ternary.String(app.data.IsValid(), "", "No account configured.\n\n")
	e := app.PopupDialog(cdtype.DialogData{
		Message: text + "Please enter your login in the format username:password",
		Buttons: "ok;cancel",
		Widget:  cdtype.DialogWidgetText{},
		Callback: cdtype.DialogCallbackValidString(func(str string) {
			app.data.SaveLogin(str)
			app.Action().Launch(ActionCheckMail) // CheckMail will launch a check and reset the timer.
		}),
	})

	app.Log().Err(e, "popup")
}
Esempio n. 6
0
File: audio.go Progetto: sqp/godock
func (app *Applet) menuAddDevices(menu cdtype.Menuer, selected dbus.ObjectPath, title string, call func(dbus.ObjectPath) error) {
	sinks, _ := app.pulse.Core().ListPath("Sinks")
	if len(sinks) < 2 { // Only show the sinks list if we have at least 2 devices to switch between.
		return
	}
	menu.AddSeparator()
	menu.AddEntry(title, "audio-card", nil)
	menu.AddSeparator()
	for _, sink := range sinks {
		dev := app.pulse.Device(sink)
		sink := sink // make static reference of sink for the callback (we're in a range).

		v, e := dev.MapString("PropertyList")
		name := ternary.String(e == nil, v["device.description"], "unknown")
		menu.AddCheckEntry(name, sink == selected, func() { log.Err(call(sink)) })
	}
}
Esempio n. 7
0
// ListScreens returns the list of screens.
//
func (Data) ListScreens() (list []datatype.Field) {
	nb := desktops.NbScreens()
	if nb <= 1 {
		return []datatype.Field{{Key: "0", Name: "Use all screens"}}
	}

	var xmax, ymax int
	for i := 0; i < nb; i++ {
		x, y := desktops.ScreenPosition(i)
		xmax = ternary.Max(x, xmax)
		ymax = ternary.Max(y, ymax)
	}

	for i := 0; i < nb; i++ {
		var xstr, ystr string
		x, y := desktops.ScreenPosition(i)
		if xmax > 0 { // at least 2 screens horizontally
			switch {
			case x == 0:
				xstr = "left"
			case x == xmax:
				xstr = "right"
			default:
				xstr = "middle"
			}
		}

		if ymax > 0 { // at least 2 screens vertically
			switch {
			case y == 0:
				ystr = "top"
			case y == ymax:
				ystr = "bottom"
			default:
				ystr = "middle"
			}
		}
		key := strconv.Itoa(i)
		sep := ternary.String(xstr != "" && ystr != "", " - ", "")
		name := "Screen" + " " + key + " (" + xstr + sep + ystr + ")"

		list = append(list, datatype.Field{Key: key, Name: name})
	}
	return list
}
Esempio n. 8
0
File: icon.go Progetto: sqp/godock
func (o *dockIcon) DefaultNameIcon() (name, img string) {
	switch {
	case o.IsApplet():
		vc := o.ModuleInstance().Module().VisitCard()
		return vc.GetTitle(), vc.GetIconFilePath()

	case o.IsSeparator():
		return "--------", ""

	case o.IsLauncher(), o.IsStackIcon(), o.IsAppli(), o.IsClassIcon():
		name := o.GetClass().Name()
		if name != "" {
			return name, o.GetFileName() // o.GetClassInfo(ClassIcon)
		}
		return ternary.String(o.GetInitialName() != "", o.GetInitialName(), o.GetName()), o.GetFileName()

	}
	return o.GetName(), o.GetFileName()
}
Esempio n. 9
0
File: clouds.go Progetto: sqp/godock
// Check gets and displays updated weather informations.
//
func (app *Applet) Check() {
	var (
		fail  int
		count int
		errs  []string
	)
	for e := range app.weather.Get() {
		count++
		if app.Log().Err(e, "get data") {
			fail++
			errs = append(errs, e.Error())
		}
	}
	if fail == 0 {
		app.Draw()
	} else {
		all := ternary.String(fail == count, " All failed", "")
		msg := "Get weather errors:" + all + "\n" + strings.Join(errs, "\n")
		app.ShowDialog(msg, app.conf.DialogDuration)
	}
}
Esempio n. 10
0
func (lf *lineFeed) valueUpdated(key *cftype.Key, line tablist.Liner) {
	flag := false
	older := key.Storage().Valuer(key.Group, key.Name)
	valStatus := key.ValueState(older)

	for i, st := range valStatus {
		curline := lf.testNewLine(line, i)
		switch st.State {

		case cftype.StateBothEmpty:
			line.Colored(RowOld, color.FgMagenta, "**EMPTY**")
			line.Colored(RowNew, color.BgRed, "  ==  ")

		case cftype.StateUnchanged:
			curline.Set(RowOld, st.Old)
			curline.Colored(RowNew, color.BgRed, "  ==  ")

		case cftype.StateEdited:
			curline.Set(RowOld, st.Old)
			st.New = ternary.String(st.New == "", "**EMPTY**", st.New)
			curline.Colored(RowNew, color.FgGreen, st.New)
			flag = true

		case cftype.StateAdded:
			curline.Set(RowOld, "**EMPTY**")
			curline.Colored(RowNew, color.FgGreen, st.New)
			flag = true

		case cftype.StateRemoved:
			curline.Set(RowOld, st.Old)
			curline.Colored(RowNew, color.FgGreen, "**EMPTY**")
			flag = true
		}
	}

	if flag {
		lf.countChanged++
	}
}
Esempio n. 11
0
func dialogAskBackend() {
	// Need to keep the string as it is for translation.
	str := "OpenGL allows you to use the hardware acceleration, reducing the CPU load to the minimum.\nIt also allows some pretty visual effects similar to Compiz.\nHowever, some cards and/or their drivers don't fully support it, which may prevent the dock from running correctly.\nDo you want to activate OpenGL ?\n (To not show this dialog, launch the dock from the Application menu,\n  or with the -o option to force OpenGL and -c to force cairo.)"

	dialog := newgtk.Dialog()
	dialog.SetTitle(tran.Slate("Use OpenGL in Cairo-Dock"))
	dialog.AddButton(tran.Slate("Yes"), gtk.RESPONSE_YES)
	dialog.AddButton(tran.Slate("No"), gtk.RESPONSE_NO)

	labelTxt := newgtk.Label(tran.Slate(str))

	content, _ := dialog.GetContentArea()
	content.PackStart(labelTxt, false, false, 0)

	askBox := newgtk.Box(gtk.ORIENTATION_HORIZONTAL, 3)
	content.PackStart(askBox, false, false, 0)

	labelSave := newgtk.Label(tran.Slate("Remember this choice"))
	check := newgtk.CheckButton()
	askBox.PackEnd(check, false, false, 0)
	askBox.PackEnd(labelSave, false, false, 0)

	dialog.ShowAll()

	answer := dialog.Run() // has its own main loop, so we can call it before gtk_main.
	remember := check.GetActive()
	dialog.Destroy()

	if answer == int(gtk.RESPONSE_NO) {
		gldi.GLBackendDeactivate()
	}

	if remember { // save user choice to file.
		value := ternary.String(gtk.ResponseType(answer) == gtk.RESPONSE_YES, "opengl", "cairo")
		updateHiddenFile("default backend", value)
	}
}
Esempio n. 12
0
File: editui.go Progetto: sqp/godock
func formatBool(val bool) string {
	return ternary.String(val, "Yes", "No")
}
Esempio n. 13
0
// indent returns 2 space of indent for keys in a frame.
//
func (lf *lineFeed) indent() string {
	return ternary.String(lf.hasFrame, "  ", "")
}
Esempio n. 14
0
// DialogQuality prepares a dialog to ask the desired quality and download.
//
func (m *Manager) DialogQuality(filterFormats FuncFilterFormats, callDialog FuncPopupDialog, callDL DownloadFunc, vid *Video) {
	if vid.Name == "" {
		var e error
		vid.Name, e = vid.filer.Title()
		if m.log.Err(e, "videodl: missing title") {
			return
		}
	}

	formats, e := vid.filer.Formats()
	if m.log.Err(e, "format") || len(formats) == 0 {
		return
	}

	// formats = append(formats,
	// Format{Res: QualityBestFound.String(), Code: "best"},
	// Format{Res: QualityBestPossible.String()},
	// )

	// Reduce list of formats.
	formats = filterFormats(formats)

	var ids []string
	for _, form := range formats {
		size := "?"
		if form.Size > 0 {
			size = strconv.Itoa(form.Size)
		}

		ids = append(ids, size+" MB\t"+
			form.Extension+"\t"+form.Resolution+"\t"+
			form.AudioEncoding+"\t"+form.VideoEncoding,
		)
	}

	ids = append(ids, "Category: "+m.category)
	if vid.Format != nil {
		if vid.Format.needDeleteFile == "" {
			vid.Format.needDeleteFile = vid.Extension
		} else {
			vid.Format.needDeleteFile = ""
		}
		ids = append(ids, "Delete current file: "+ternary.String(vid.Format.needDeleteFile != "", "Yes", "No"))

	}

	e = callDialog(cdtype.DialogData{
		Message: vid.Name + "\n\nSelect quality:",
		// UseMarkup: true,
		Widget: cdtype.DialogWidgetList{
			Values:       ids,
			InitialValue: 0,
		},
		Buttons: "ok;cancel",
		Callback: cdtype.DialogCallbackValidInt(func(id int) {
			switch {
			case id > len(formats)+1:
				m.log.NewErr("ID out of range", "videodl DialogQuality")

			case id == len(formats)+1:
				if vid.Format == nil {
					m.log.NewErr("select delete file but format missing", "videodl DialogQuality")
				} else {
					m.DialogQuality(filterFormats, callDialog, callDL, vid)
				}

			case id == len(formats):
				m.DialogCategory(filterFormats, callDialog, callDL, vid)

			default:
				callDL(vid, formats[id])
			}
		}),
	})
	m.log.Err(e, "popup")
}
Esempio n. 15
0
// Entry adds a defined entry to the menu. Returns if a separator is needed.
//
func (m *DockMenu) Entry(entry MenuEntry) bool {
	switch entry {

	case MenuAbout:
		m.AddEntry(
			tran.Slate("About"),
			globals.IconNameAbout,
			about.New,
		)

	case MenuAddApplet:
		m.AddEntry(
			tran.Slate("Applet"),
			globals.IconNameAdd,
			backendgui.ShowAddons)

	case MenuAddLauncher:
		m.AddEntry(
			tran.Slate("Custom launcher"),
			globals.IconNameAdd,
			func() {
				newIcon := gldi.LauncherAddNew("", m.Dock, nextOrder(m.Icon, m.Dock))
				if newIcon == nil {
					// TODO: use log
					println("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders")
				} else {
					backendgui.ShowItems(newIcon, nil, nil, -1)
				}
			},
		).SetTooltipText(tran.Slate("Usually you would drag a launcher from the menu and drop it on the dock."))

	case MenuAddMainDock:
		m.AddEntry(
			tran.Slate("Main dock"),
			globals.IconNameAdd,
			func() {
				key := gldi.DockAddConfFile()
				gldi.DockNew(key)

				backendgui.ReloadItems()

				// g_timeout_add_seconds (1, (GSourceFunc)_show_new_dock_msg, cDockName);  // delai, car sa fenetre n'est pas encore bien placee (0,0).
			})

	case MenuAddSeparator:
		m.AddEntry(
			tran.Slate("Separator"),
			globals.IconNameAdd,
			func() {
				newIcon := gldi.SeparatorIconAddNew(m.Dock, nextOrder(m.Icon, m.Dock))
				if newIcon == nil {
					// TODO: use log
					println("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders")
				}
			})

	case MenuAddSubDock:
		m.AddEntry(
			tran.Slate("Sub-dock"),
			globals.IconNameAdd,
			func() {
				newIcon := gldi.StackIconAddNew(m.Dock, nextOrder(m.Icon, m.Dock))
				if newIcon == nil {
					// TODO: use log
					println("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders")
				}
			})

	case MenuClassItems:
		//\_________________________ class actions.
		items := m.Icon.GetClass().MenuItems()
		for _, it := range items {
			cmd := strings.Fields(it[1])
			m.AddEntry(
				it[0], // name
				it[2], // icon
				func() { log.ExecAsync(cmd[0], cmd[1:]...) }) // was gldi.LaunchCommand(cmd)
		}
		return len(items) > 0

	case MenuConfigure:
		m.AddEntry(
			tran.Slate("Configure"),
			globals.IconNamePreferences,
			backendgui.ShowMainGui,
		).SetTooltipText(tran.Slate("Configure behaviour, appearance, and applets."))

	case MenuCustomIconRemove:
		classIcon := m.Icon.GetClass().Icon()
		if classIcon == "" {
			classIcon = m.Icon.GetClass().String()
		}

		path := filepath.Join(globals.DirCurrentIcons(), classIcon+".png")
		if _, e := os.Stat(path); e != nil {
			path = filepath.Join(globals.DirCurrentIcons(), classIcon+".svg")
			if _, e := os.Stat(path); e != nil {
				path = ""
			}
		}

		// println("custom icon", path)

		if path != "" {
			m.AddEntry(
				tran.Slate("Remove custom icon"),
				globals.IconNameRemove,
				func() {
					C._cairo_dock_remove_custom_appli_icon((*C.Icon)(unsafe.Pointer(m.Icon.ToNative())), (*C.CairoDock)(unsafe.Pointer(m.Dock.Ptr)))
				})
		}

	case MenuCustomIconSet:
		m.AddEntry(
			tran.Slate("Set a custom icon"),
			globals.IconNameSelectColor,
			func() {
				C._cairo_dock_set_custom_appli_icon((*C.Icon)(unsafe.Pointer(m.Icon.ToNative())), (*C.CairoDock)(unsafe.Pointer(m.Dock.Ptr)))
			})

	case MenuDeleteDock:
		m.AddEntry(
			tran.Slate("Delete this dock"),
			globals.IconNameDelete,
			func() {
				if m.Dock.GetRefCount() != 0 {
					dialog.ShowWithQuestion("Delete this dock?",
						m.Dock.GetPointedIcon(),
						m.Container,
						globals.FileCairoDockIcon(),
						cbDialogIsOK(func() {
							gldi.ObjectDelete(m.Dock)
						}))
				}
			})

	case MenuDeskletLock:
		desklet := m.Container.ToDesklet()
		m.AddCheckEntry(
			tran.Slate("Lock position"),
			desklet.PositionLocked(),
			func(c *gtk.CheckMenuItem) {
				desklet.LockPosition(c.GetActive())
				backendgui.UpdateDeskletVisibility(desklet)
			})

	case MenuDeskletSticky:
		desklet := m.Container.ToDesklet()
		m.AddCheckEntry(
			tran.Slate("On all desktops"),
			m.Container.ToDesklet().IsSticky(),
			func(c *gtk.CheckMenuItem) {
				desklet.SetSticky(c.GetActive())

				// TODO: check why SetSticky isn't working...
				println("get stick", desklet.IsSticky())

				backendgui.UpdateDeskletVisibility(desklet)
			})

	case MenuDeskletVisibility:
		submenu := m.AddSubMenu(tran.Slate("Visibility"), globals.IconNameFind)

		desklet := m.Container.ToDesklet()

		callback := func(radio *gtk.RadioMenuItem, val cdtype.DeskletVisibility) {
			if radio.GetActive() {
				desklet.SetVisibility(val, true) // with true, also save to conf.
				backendgui.UpdateDeskletVisibility(desklet)
			}
		}

		group := 42
		visibility := desklet.Visibility()
		addRadio := func(vis cdtype.DeskletVisibility, label string) {
			radio := submenu.AddRadioEntry(label, visibility == vis, group, nil)
			radio.Connect("toggled", callback, vis)
		}

		addRadio(cdtype.DeskletVisibilityNormal, tran.Slate("Normal"))
		addRadio(cdtype.DeskletVisibilityKeepAbove, tran.Slate("Always on top"))
		addRadio(cdtype.DeskletVisibilityKeepBelow, tran.Slate("Always below"))
		if gldi.CanSetOnWidgetLayer() {
			addRadio(cdtype.DeskletVisibilityWidgetLayer, tran.Slate("Widget Layer"))
		}
		addRadio(cdtype.DeskletVisibilityReserveSpace, tran.Slate("Reserve space"))

	case MenuDetachApplet:
		m.AddEntry(
			ternary.String(m.Dock != nil, tran.Slate("Detach"), tran.Slate("Return to the dock")),
			ternary.String(m.Dock != nil, globals.IconNameGotoTop, globals.IconNameGotoBottom),
			func() {
				// if (CAIRO_DOCK_IS_DESKLET (pContainer))
				// 	icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
				// g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));

				m.Icon.ModuleInstance().Detach()
			})

	case MenuDuplicateApplet:
		m.AddEntry(
			tran.Slate("Duplicate"),
			globals.IconNameAdd,
			func() {
				// if (CAIRO_DOCK_IS_DESKLET (pContainer))
				// 	icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
				// g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));

				m.Icon.ModuleInstance().Module().AddInstance()
				// gldi_module_add_instance (icon->pModuleInstance->pModule);
			})

	case MenuEditApplet:
		m.AddEntry(
			tran.Slate("Edit"),
			globals.IconNameEdit,
			func() {
				// if (CAIRO_DOCK_IS_DESKLET (pContainer))
				// 	icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module.
				// g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
				backendgui.ShowItems(m.Icon, nil, nil, -1)
			})

	case MenuEditDock:
		m.AddEntry(
			tran.Slate("Configure this dock"),
			globals.IconNameExecute,
			func() { backendgui.ShowItems(nil, m.Container, nil, 0) },
		).SetTooltipText(tran.Slate("Customize the position, visibility and appearance of this main dock."))

	case MenuEditIcon:
		m.AddEntry(tran.Slate(
			tran.Slate("Edit")),
			globals.IconNameEdit,
			func() {
				switch m.Icon.GetDesktopFileName() {
				case "", "none":
					dialog.ShowTemporaryWithIcon("Sorry, this icon doesn't have a configuration file.", m.Icon, m.Container, 4000, "same icon")

				default:
					backendgui.ShowItems(m.Icon, nil, nil, -1)
				}
			})

	case MenuEditTarget:
		_, img := m.Icon.DefaultNameIcon()
		m.AddEntry(
			tran.Slate("Edit icon"),
			img,
			func() {
				// if (CAIRO_DOCK_IS_DESKLET (pContainer))
				// 	icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module.
				// g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
				backendgui.ShowItems(m.Icon, nil, nil, -1)
			})

	case MenuHandbook:
		m.AddEntry(
			tran.Slate("Applet's handbook"),
			globals.IconNameAbout,
			m.Icon.ModuleInstance().PopupAboutApplet)

		// handbook + 5x to facto
		// picon := icon
		// if container.IsDesklet() {
		// 	picon = container.Icon()
		// 	icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
		// }

	case MenuHelp:
		m.AddEntry(
			tran.Slate("Help"),
			globals.IconNameHelp,
			func() { backendgui.ShowModuleGui("Help") },
		).SetTooltipText(tran.Slate("There are no problems, only solutions (and a lot of useful hints!)"))

	case MenuLaunchNew:
		m.AddEntry(
			tran.Slate("Launch a new (Shift+clic)"),
			globals.IconNameAdd,
			func() { m.Icon.LaunchCommand(log) })

	case MenuLockIcons:
		m.AddCheckEntry(
			tran.Slate("Lock icons position"),
			current.Docks.LockIcons(),
			func() {
				current.Docks.LockIcons(!current.Docks.LockIcons())
				config.UpdateFile(log, globals.ConfigFile(), "Accessibility", "lock icons", current.Docks.LockIcons())
			},
		).SetTooltipText(tran.Slate("This will (un)lock the position of the icons."))

	case MenuMakeLauncher:
		m.AddEntry(
			tran.Slate("Make it a launcher"),
			globals.IconNameNew,
			func() {
				C._cairo_dock_make_launcher_from_appli((*C.Icon)(unsafe.Pointer(m.Icon.ToNative())), (*C.CairoDock)(unsafe.Pointer(m.Dock.Ptr)))
			})

	case MenuMoveToDesktopClass:
		m.moveToDesktop(true)

	case MenuMoveToDesktopWindow:
		m.moveToDesktop(false)

	case MenuMoveToDock:
		sub := m.AddSubMenu(tran.Slate("Move to another dock"), globals.IconNameJumpTo)

		docks := gldi.GetAllAvailableDocks(m.Icon.GetContainer().ToCairoDock(), m.Icon.GetSubDock())
		docks = append(docks, nil)
		for _, dock := range docks {
			name := ""
			key := ""
			icon := ""
			if dock == nil {
				name = tran.Slate("New main dock")
				icon = globals.IconNameAdd // globals.IconNameNew
			} else {
				name = ternary.String(dock.GetReadableName() != "", dock.GetReadableName(), dock.GetDockName())
				key = dock.GetDockName()

				if dock.GetRefCount() == 0 { // Maindocks icon
					switch dock.Container().ScreenBorder() {
					case cdtype.ContainerPositionBottom:
						icon = "go-down"
					case cdtype.ContainerPositionTop:
						icon = "go-up"
					case cdtype.ContainerPositionLeft:
						icon = "go-previous"
					case cdtype.ContainerPositionRight:
						icon = "go-next"
					}
				} else { // Subdocks icon.
					dockicon := dock.SearchIconPointingOnDock(nil)
					if dockicon != nil {
						icon = dockicon.GetFileName()
					}
				}

			}
			sub.AddEntry(
				name,
				icon,
				func() {
					if key == "" {
						key = gldi.DockAddConfFile()
					}

					m.Icon.WriteContainerNameInConfFile(key) // Update icon conf file.

					if m.Icon.IsLauncher() || m.Icon.IsStackIcon() || m.Icon.IsSeparator() { // Reload icon (creating the dock).
						gldi.ObjectReload(m.Icon)

					} else if m.Icon.IsApplet() {
						gldi.ObjectReload(m.Icon.ModuleInstance())
					}

					newdock := gldi.DockGet(key)
					if newdock != nil && newdock.GetRefCount() == 0 && len(newdock.Icons()) == 1 {
						str := tran.Slate("The new dock has been created.\nYou can customize it by right-clicking on it -> cairo-dock -> configure this dock.")
						dialog.ShowGeneralMessage(str, 8000) // we don't show it on the new dock as its window isn't positioned yet (0,0).
					}
				})
		}

	case MenuQuickHide:
		m.AddEntry(
			tran.Slate("Quick-Hide"),
			globals.IconNameGotoBottom,
			gldi.QuickHideAllDocks,
		).SetTooltipText(tran.Slate("This will hide the dock until you hover over it with the mouse."))

	case MenuQuit:
		item := m.AddEntry(
			tran.Slate("Quit"),
			globals.IconNameQuit,
			func() {
				backendgui.CloseGui()

				// gtk.MainQuit() // TODO: remove SQP HACK, easy quit no confirm for tests.

				dialog.ShowWithQuestion("Quit Cairo-Dock?",
					GetIconForDesklet(m.Icon, m.Container),
					m.Container,
					globals.FileCairoDockIcon(),
					cbDialogIsOK(gtk.MainQuit))
			})

		// const gchar *cDesktopSession = g_getenv ("DESKTOP_SESSION");
		// gboolean bIsCairoDockSession = cDesktopSession && g_str_has_prefix (cDesktopSession, "cairo-dock");

		// 	// if we're using a Cairo-Dock session and we quit the dock we have... nothing to relaunch it!
		// 	if bIsCairoDockSession {

		// item.SetSensitive(false)
		// item.SetTooltipText("You're using a Cairo-Dock Session!\nIt's not advised to quit the dock but you can press Shift to unlock this menu entry.")

		// static void _cairo_dock_set_sensitive_quit_menu (G_GNUC_UNUSED GtkWidget *pMenuItem, GdkEventKey *pKey, GtkWidget *pQuitEntry)
		// {
		// pMenuItem not used because we want to only modify one entry
		// 	if (pKey->type == GDK_KEY_PRESS &&
		// 		(pKey->keyval == GDK_KEY_Shift_L ||
		// 		pKey->keyval == GDK_KEY_Shift_R)) // pressed
		// 		gtk_widget_set_sensitive (pQuitEntry, TRUE); // unlocked
		// 	else if (pKey->state & GDK_SHIFT_MASK) // released
		// 		gtk_widget_set_sensitive (pQuitEntry, FALSE); // locked)
		// }
		cbSensitive := func(_ *gtk.CheckMenuItem, event *gdk.Event) {
			key := &gdk.EventKey{Event: event}

			println("key", key.KeyVal())

			if key.KeyVal() == uint(C.GDK_KEY_Shift_R) { // pressed.
				item.SetSensitive(true)

			} else if gdk.ModifierType(key.State())&gdk.GDK_SHIFT_MASK > 0 { // released.
				item.SetSensitive(false)
			}
		}

		_, e := item.Connect("key-press-event", cbSensitive)
		if e != nil {
			println((e.Error()))
		}
		item.Connect("key-release-event", cbSensitive)

		// 		gtk_widget_set_sensitive (pMenuItem, FALSE); // locked
		// 		gtk_widget_set_tooltip_text (pMenuItem, _("You're using a Cairo-Dock Session!\nIt's not advised to quit the dock but you can press Shift to unlock this menu entry."));
		// 		// signal to unlock the entry (signal monitored only in the submenu)
		// 		g_signal_connect (pSubMenu, "key-press-event", G_CALLBACK (_cairo_dock_set_sensitive_quit_menu), pMenuItem);
		// 		g_signal_connect (pSubMenu, "key-release-event", G_CALLBACK (_cairo_dock_set_sensitive_quit_menu), pMenuItem);
		// 	}

		// case MenuAutostart:

		// 	gchar *cCairoAutoStartDirPath = g_strdup_printf ("%s/.config/autostart", g_getenv ("HOME"));
		// 	gchar *cCairoAutoStartEntryPath = g_strdup_printf ("%s/cairo-dock.desktop", cCairoAutoStartDirPath);
		// 	gchar *cCairoAutoStartEntryPath2 = g_strdup_printf ("%s/cairo-dock-cairo.desktop", cCairoAutoStartDirPath);
		// 	if (! bIsCairoDockSession && ! g_file_test (cCairoAutoStartEntryPath, G_FILE_TEST_EXISTS) && ! g_file_test (cCairoAutoStartEntryPath2, G_FILE_TEST_EXISTS))
		// 	{
		// 		cairo_dock_add_in_menu_with_stock_and_data (_("Launch Cairo-Dock on startup"),
		// 			GLDI_ICON_NAME_ADD,
		// 			G_CALLBACK (_cairo_dock_add_autostart),
		// 			pSubMenu,
		// 			NULL);
		// 	}
		// 	g_free (cCairoAutoStartEntryPath);
		// 	g_free (cCairoAutoStartEntryPath2);
		// 	g_free (cCairoAutoStartDirPath);

		// case MenuThirdParty:

		// 	pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Get more applets!"),
		// 		GLDI_ICON_NAME_ADD,
		// 		G_CALLBACK (_cairo_dock_show_third_party_applets),
		// 		pSubMenu,
		// 		NULL);
		// 	gtk_widget_set_tooltip_text (pMenuItem, _("Third-party applets provide integration with many programs, like Pidgin"));

	case MenuRemoveApplet:
		m.AddEntry(
			tran.Slate("Remove"),
			globals.IconNameRemove,
			func() {
				// if (CAIRO_DOCK_IS_DESKLET (pContainer))
				// 	icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
				// g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));

				dialog.ShowWithQuestion(
					fmt.Sprintf("You're about to remove this applet (%s) from the dock. Are you sure?", m.Icon.ModuleInstance().Module().VisitCard().GetTitle()),
					m.Icon,
					m.Container,
					"same icon",
					cbDialogIsOK(func() {
						gldi.ObjectDelete(m.Icon.ModuleInstance())
					}))
			})

	case MenuRemoveIcon:
		m.AddEntry(
			tran.Slate("Remove"),
			globals.IconNameRemove,
			func() {
				name := ternary.String(m.Icon.GetInitialName() != "", m.Icon.GetInitialName(), m.Icon.GetName())
				if name == "" {
					name = ternary.String(m.Icon.IsSeparator(), tran.Slate("separator"), "no name")
				}
				dialog.ShowWithQuestion(
					fmt.Sprintf(tran.Slate("You're about to remove this icon (%s) from the dock. Are you sure?"), name),
					m.Icon,
					m.Container,
					"same icon",
					cbDialogIsOK(func() {
						if m.Icon.IsStackIcon() && m.Icon.GetSubDock() != nil && len(m.Icon.GetSubDock().Icons()) > 0 {
							dialog.ShowWithQuestion(
								tran.Slate("Do you want to re-dispatch the icons contained inside this container into the dock?\n(otherwise they will be destroyed)"),
								m.Icon,
								m.Container,
								globals.FileCairoDockIcon(),
								cbDialogIsOK(func() {
									m.Icon.RemoveIconsFromSubdock(m.Dock)
								}))
						}

						m.Icon.RemoveFromDock()
					}))
			}).SetTooltipText(tran.Slate("You can remove a launcher by dragging it out of the dock with the mouse ."))

	case MenuThemes:
		// 		pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Manage themes"),
		// 			CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-appearance.svg",
		// 			G_CALLBACK (_cairo_dock_initiate_theme_management),
		// 			pSubMenu,
		// 			NULL);
		// 		gtk_widget_set_tooltip_text (pMenuItem, _("Choose from amongst many themes on the server or save your current theme."));

	case MenuWindowAbove:
		flag := m.Icon.Window().IsAbove()
		m.AddEntry(
			ternary.String(flag, tran.Slate("Don't keep above"), tran.Slate("Keep above")),
			ternary.String(flag, globals.IconNameGotoBottom, globals.IconNameGotoTop),
			m.Icon.CallbackActionWindowToggle((cdglobal.Window).SetAbove, (cdglobal.Window).IsAbove))

	case MenuWindowBelow:
		if !m.Icon.Window().IsHidden() { // this could be a button in the menu, if we find an icon that doesn't look too much like the "minimise" one
			m.AddEntry(
				tran.Slate("Below other windows")+actionMiddleClick(m.Icon, 4),
				globals.DirShareData("icons", "icon-lower.svg"),
				m.Icon.CallbackActionWindow((cdglobal.Window).Lower))
		}

	case MenuWindowFullScreen:
		flag := m.Icon.Window().IsFullScreen()
		m.AddEntry(
			ternary.String(flag, tran.Slate("Not Fullscreen"), tran.Slate("Fullscreen")),
			ternary.String(flag, globals.IconNameLeaveFullScreen, globals.IconNameFullScreen),
			m.Icon.CallbackActionWindowToggle((cdglobal.Window).SetFullScreen, (cdglobal.Window).IsFullScreen))

	case MenuWindowKill:
		m.AddEntry(
			tran.Slate("Kill"),
			globals.IconNameClose,
			m.Icon.CallbackActionWindow((cdglobal.Window).Kill))

	case MenuWindowMoveAllHere:
		m.AddEntry(
			tran.Slate("Move all to this desktop"),
			globals.IconNameJumpTo,
			m.Icon.CallbackActionSubWindows((cdglobal.Window).MoveToCurrentDesktop))

	case MenuWindowMoveHere:
		var callback func()
		if !m.Icon.Window().IsOnCurrentDesktop() {
			callback = m.Icon.CallbackActionWindow(func(win cdglobal.Window) {
				win.MoveToCurrentDesktop()
				if !win.IsHidden() {
					win.Show()
				}
			})
		}
		m.AddEntry(tran.Slate("Move to this desktop"), globals.IconNameJumpTo, callback)

	case MenuWindowSticky:
		m.AddEntry(
			ternary.String(m.Icon.Window().IsSticky(), tran.Slate("Visible only on this desktop"), tran.Slate("Visible on all desktops")),
			globals.IconNameJumpTo,
			m.Icon.CallbackActionWindowToggle((cdglobal.Window).SetSticky, (cdglobal.Window).IsSticky))

	}
	return notif.AnswerLetPass
}