Stanislav Nikitin
9273273b49
Added language selection combobox in options dialog. Selecting language here will overwrite language code gathered from system. Added AcceptedLanguages map to Translator, which holds readable names and lang-country codes with avaailable languages. Filled it with languages in which URTrator already translated. Francais coming :)
435 lines
16 KiB
Go
435 lines
16 KiB
Go
// URTator - Urban Terror server browser and game launcher, written in
|
|
// Go.
|
|
//
|
|
// Copyright (c) 2016, Stanslav N. a.k.a pztrn (or p0z1tr0n)
|
|
// All rights reserved.
|
|
//
|
|
// Licensed under Terms and Conditions of GNU General Public License
|
|
// version 3 or any higher.
|
|
// ToDo: put full text of license here.
|
|
package ui
|
|
|
|
import (
|
|
// stdlib
|
|
"fmt"
|
|
"runtime"
|
|
|
|
// Local
|
|
"github.com/pztrn/urtrator/datamodels"
|
|
|
|
// Other
|
|
"github.com/mattn/go-gtk/gtk"
|
|
"github.com/mattn/go-gtk/glib"
|
|
)
|
|
|
|
type OptionsDialog struct {
|
|
// Window.
|
|
window *gtk.Window
|
|
// Options main VBox.
|
|
vbox *gtk.VBox
|
|
// Tabs widget.
|
|
tab_widget *gtk.Notebook
|
|
|
|
// Widgets.
|
|
// General tab.
|
|
// Show tray icon checkbutton.
|
|
show_tray_icon *gtk.CheckButton
|
|
// Enable autoupdate checkbutton.
|
|
autoupdate *gtk.CheckButton
|
|
// Appearance tab.
|
|
// Language to use.
|
|
language_combo *gtk.ComboBoxText
|
|
// Urban Terror tab.
|
|
// Profiles list.
|
|
profiles_list *gtk.TreeView
|
|
// Servers updating tab.
|
|
// Master server address.
|
|
master_server_addr *gtk.Entry
|
|
// Servers autoupdate.
|
|
servers_autoupdate *gtk.CheckButton
|
|
// Timeout for servers autoupdating.
|
|
servers_autoupdate_timeout *gtk.Entry
|
|
|
|
// Data stores.
|
|
// Urban Terror profiles list.
|
|
profiles_list_store *gtk.ListStore
|
|
}
|
|
|
|
func (o *OptionsDialog) addProfile() {
|
|
fmt.Println("Adding profile...")
|
|
|
|
op := OptionsProfile{}
|
|
op.Initialize(false)
|
|
ctx.Eventer.LaunchEvent("flushProfiles", map[string]string{})
|
|
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
|
ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
|
|
}
|
|
|
|
func (o *OptionsDialog) closeOptionsDialogByCancel() {
|
|
o.window.Destroy()
|
|
}
|
|
|
|
func (o *OptionsDialog) closeOptionsDialogWithDiscard() {
|
|
}
|
|
|
|
func (o *OptionsDialog) closeOptionsDialogWithSaving() {
|
|
fmt.Println("Saving changes to options...")
|
|
|
|
o.saveGeneral()
|
|
o.saveAppearance()
|
|
|
|
// Temporary disable all these modals on Linux.
|
|
// See https://github.com/mattn/go-gtk/issues/289.
|
|
if runtime.GOOS != "linux" {
|
|
mbox_string := ctx.Translator.Translate("Some options require application restart to be applied.", nil)
|
|
m := gtk.NewMessageDialog(o.window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, mbox_string)
|
|
m.Response(func() {
|
|
m.Destroy()
|
|
})
|
|
m.Run()
|
|
}
|
|
|
|
o.window.Destroy()
|
|
}
|
|
|
|
func (o *OptionsDialog) deleteProfile() {
|
|
// Oh... dat... GTK...
|
|
sel := o.profiles_list.GetSelection()
|
|
model := o.profiles_list.GetModel()
|
|
iter := new(gtk.TreeIter)
|
|
_ = sel.GetSelected(iter)
|
|
var p string
|
|
gval := glib.ValueFromNative(p)
|
|
model.GetValue(iter, 0, gval)
|
|
profile_name := gval.GetString()
|
|
|
|
if len(profile_name) > 0 {
|
|
fmt.Println("Deleting profile '" + profile_name + "'")
|
|
|
|
profile := datamodels.Profile{}
|
|
profile.Name = profile_name
|
|
ctx.Eventer.LaunchEvent("deleteProfile", map[string]string{"profile_name": profile_name})
|
|
ctx.Eventer.LaunchEvent("flushProfiles", map[string]string{})
|
|
ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
|
|
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
|
}
|
|
}
|
|
|
|
func (o *OptionsDialog) editProfile() {
|
|
// Oh... dat... GTK...
|
|
sel := o.profiles_list.GetSelection()
|
|
model := o.profiles_list.GetModel()
|
|
iter := new(gtk.TreeIter)
|
|
_ = sel.GetSelected(iter)
|
|
var p string
|
|
gval := glib.ValueFromNative(p)
|
|
model.GetValue(iter, 0, gval)
|
|
profile_name := gval.GetString()
|
|
|
|
if len(profile_name) > 0 {
|
|
op := OptionsProfile{}
|
|
op.InitializeUpdate(profile_name)
|
|
ctx.Eventer.LaunchEvent("flushProfiles", map[string]string{})
|
|
ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
|
|
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
|
}
|
|
}
|
|
|
|
func (o *OptionsDialog) fill() {
|
|
if ctx.Cfg.Cfg["/general/show_tray_icon"] == "1" {
|
|
o.show_tray_icon.SetActive(true)
|
|
}
|
|
if ctx.Cfg.Cfg["/general/urtrator_autoupdate"] == "1" {
|
|
o.autoupdate.SetActive(true)
|
|
}
|
|
|
|
// Servers updating tab.
|
|
master_server_addr, ok := ctx.Cfg.Cfg["/servers_updating/master_server"]
|
|
if !ok {
|
|
o.master_server_addr.SetText("master.urbanterror.info:27900")
|
|
} else {
|
|
o.master_server_addr.SetText(master_server_addr)
|
|
}
|
|
|
|
servers_autoupdate, ok1 := ctx.Cfg.Cfg["/servers_updating/servers_autoupdate"]
|
|
if ok1 {
|
|
if servers_autoupdate == "1" {
|
|
o.servers_autoupdate.SetActive(true)
|
|
}
|
|
}
|
|
|
|
servers_update_timeout, ok2 := ctx.Cfg.Cfg["/servers_updating/servers_autoupdate_timeout"]
|
|
if !ok2 {
|
|
o.servers_autoupdate_timeout.SetText("10")
|
|
} else {
|
|
o.servers_autoupdate_timeout.SetText(servers_update_timeout)
|
|
}
|
|
|
|
}
|
|
|
|
// Appearance tab initialization.
|
|
func (o *OptionsDialog) initializeAppearanceTab() {
|
|
appearance_vbox := gtk.NewVBox(false, 0)
|
|
|
|
appearance_table := gtk.NewTable(1, 2, false)
|
|
|
|
language_selection_tooltip := ctx.Translator.Translate("Language which URTrator will use.\n\nChanging this requires URTrator restart!", nil)
|
|
|
|
language_selection_label := gtk.NewLabel(ctx.Translator.Translate("Language:", nil))
|
|
language_selection_label.SetAlignment(0, 0)
|
|
language_selection_label.SetTooltipText(language_selection_tooltip)
|
|
appearance_table.Attach(language_selection_label, 0, 1, 0, 1, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
o.language_combo = gtk.NewComboBoxText()
|
|
o.language_combo.SetTooltipText(language_selection_tooltip)
|
|
// Get all available languages and fill combobox.
|
|
lang_idx := 0
|
|
var lang_active int = 0
|
|
for lang, _ := range ctx.Translator.AcceptedLanguages {
|
|
o.language_combo.AppendText(lang)
|
|
if ctx.Translator.AcceptedLanguages[lang] == ctx.Cfg.Cfg["/general/language"] {
|
|
lang_active = lang_idx
|
|
}
|
|
lang_idx += 1
|
|
}
|
|
o.language_combo.SetActive(lang_active)
|
|
|
|
appearance_table.Attach(o.language_combo, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
appearance_vbox.PackStart(appearance_table, false, true, 0)
|
|
o.tab_widget.AppendPage(appearance_vbox, gtk.NewLabel(ctx.Translator.Translate("Appearance", nil)))
|
|
}
|
|
|
|
func (o *OptionsDialog) initializeGeneralTab() {
|
|
general_vbox := gtk.NewVBox(false, 0)
|
|
|
|
general_table := gtk.NewTable(2, 2, false)
|
|
|
|
// Tray icon checkbox.
|
|
show_tray_icon_label := gtk.NewLabel(ctx.Translator.Translate("Show icon in tray", nil))
|
|
show_tray_icon_label.SetAlignment(0, 0)
|
|
general_table.Attach(show_tray_icon_label, 0, 1, 0, 1, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
o.show_tray_icon = gtk.NewCheckButtonWithLabel("")
|
|
o.show_tray_icon.SetTooltipText(ctx.Translator.Translate("Show icon in tray", nil))
|
|
general_table.Attach(o.show_tray_icon, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Autoupdate checkbox.
|
|
autoupdate_tooltip := ctx.Translator.Translate("Should URTrator check for updates and update itself? Not working now.", nil)
|
|
autoupdate_label := gtk.NewLabel(ctx.Translator.Translate("Automatically update URTrator?", nil))
|
|
autoupdate_label.SetTooltipText(autoupdate_tooltip)
|
|
autoupdate_label.SetAlignment(0, 0)
|
|
general_table.Attach(autoupdate_label, 0, 1, 1, 2, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
o.autoupdate = gtk.NewCheckButtonWithLabel("")
|
|
o.autoupdate.SetTooltipText(autoupdate_tooltip)
|
|
general_table.Attach(o.autoupdate, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Vertical separator.
|
|
sep := gtk.NewVBox(false, 0)
|
|
|
|
general_vbox.PackStart(general_table, false, true, 0)
|
|
general_vbox.PackStart(sep, false, true, 0)
|
|
|
|
o.tab_widget.AppendPage(general_vbox, gtk.NewLabel(ctx.Translator.Translate("General", nil)))
|
|
}
|
|
|
|
func (o *OptionsDialog) initializeServersOptionsTab() {
|
|
servers_options_vbox := gtk.NewVBox(false, 0)
|
|
|
|
servers_updating_table := gtk.NewTable(3, 2, false)
|
|
servers_updating_table.SetRowSpacings(2)
|
|
|
|
// Master server address.
|
|
master_server_addr_tooltip := ctx.Translator.Translate("Address of master server. Specify in form: addr:port.", nil)
|
|
master_server_addr_label := gtk.NewLabel(ctx.Translator.Translate("Master server address", nil))
|
|
master_server_addr_label.SetTooltipText(master_server_addr_tooltip)
|
|
master_server_addr_label.SetAlignment(0, 0)
|
|
servers_updating_table.Attach(master_server_addr_label, 0, 1, 0, 1, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
o.master_server_addr = gtk.NewEntry()
|
|
o.master_server_addr.SetTooltipText(master_server_addr_tooltip)
|
|
servers_updating_table.Attach(o.master_server_addr, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Servers autoupdate checkbox.
|
|
servers_autoupdate_cb_tooptip := ctx.Translator.Translate("Should servers be automatically updated?", nil)
|
|
servers_autoupdate_cb_label := gtk.NewLabel(ctx.Translator.Translate("Servers autoupdate", nil))
|
|
servers_autoupdate_cb_label.SetTooltipText(servers_autoupdate_cb_tooptip)
|
|
servers_autoupdate_cb_label.SetAlignment(0, 0)
|
|
servers_updating_table.Attach(servers_autoupdate_cb_label, 0, 1 ,1, 2, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
o.servers_autoupdate = gtk.NewCheckButtonWithLabel("")
|
|
o.servers_autoupdate.SetTooltipText(servers_autoupdate_cb_tooptip)
|
|
servers_updating_table.Attach(o.servers_autoupdate, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Servers update timeout.
|
|
servers_autoupdate_timeout_tooltip := ctx.Translator.Translate("Timeout which will trigger servers information update, in minutes.", nil)
|
|
servers_autoupdate_label := gtk.NewLabel(ctx.Translator.Translate("Servers update timeout (minutes)", nil))
|
|
servers_autoupdate_label.SetTooltipText(servers_autoupdate_timeout_tooltip)
|
|
servers_autoupdate_label.SetAlignment(0, 0)
|
|
servers_updating_table.Attach(servers_autoupdate_label, 0, 1, 2, 3, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
o.servers_autoupdate_timeout = gtk.NewEntry()
|
|
o.servers_autoupdate_timeout.SetTooltipText(servers_autoupdate_timeout_tooltip)
|
|
servers_updating_table.Attach(o.servers_autoupdate_timeout, 1, 2, 2, 3, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Vertical separator.
|
|
sep := gtk.NewVBox(false, 0)
|
|
|
|
servers_options_vbox.PackStart(servers_updating_table, false, true, 0)
|
|
servers_options_vbox.PackStart(sep, true, true, 0)
|
|
|
|
o.tab_widget.AppendPage(servers_options_vbox, gtk.NewLabel(ctx.Translator.Translate("Servers updating", nil)))
|
|
}
|
|
|
|
func (o *OptionsDialog) initializeStorages() {
|
|
// Structure:
|
|
// Name|Version|Second X session
|
|
o.profiles_list_store = gtk.NewListStore(glib.G_TYPE_STRING, glib.G_TYPE_STRING, glib.G_TYPE_BOOL)
|
|
}
|
|
|
|
func (o *OptionsDialog) initializeTabs() {
|
|
o.initializeStorages()
|
|
o.tab_widget = gtk.NewNotebook()
|
|
o.tab_widget.SetTabPos(gtk.POS_LEFT)
|
|
|
|
o.initializeGeneralTab()
|
|
o.initializeAppearanceTab()
|
|
o.initializeUrtTab()
|
|
o.initializeServersOptionsTab()
|
|
|
|
// Buttons for saving and discarding changes.
|
|
buttons_hbox := gtk.NewHBox(false, 0)
|
|
sep := gtk.NewHBox(false, 0)
|
|
|
|
cancel_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("Cancel", nil))
|
|
cancel_button.Clicked(o.closeOptionsDialogByCancel)
|
|
|
|
ok_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("OK", nil))
|
|
ok_button.Clicked(o.closeOptionsDialogWithSaving)
|
|
|
|
buttons_hbox.PackStart(sep, true, true, 5)
|
|
buttons_hbox.PackStart(cancel_button, false, true, 5)
|
|
buttons_hbox.PackStart(ok_button, false, true, 5)
|
|
|
|
o.vbox.PackStart(o.tab_widget, true, true, 5)
|
|
o.vbox.PackStart(buttons_hbox, false, true, 5)
|
|
|
|
ctx.Eventer.AddEventHandler("loadProfilesIntoOptionsWindow", o.loadProfiles)
|
|
}
|
|
|
|
func (o *OptionsDialog) initializeUrtTab() {
|
|
urt_hbox := gtk.NewHBox(false, 5)
|
|
|
|
// Profiles list.
|
|
o.profiles_list = gtk.NewTreeView()
|
|
o.profiles_list.SetTooltipText(ctx.Translator.Translate("All available profiles", nil))
|
|
urt_hbox.Add(o.profiles_list)
|
|
o.profiles_list.SetModel(o.profiles_list_store)
|
|
o.profiles_list.AppendColumn(gtk.NewTreeViewColumnWithAttributes(ctx.Translator.Translate("Profile name", nil), gtk.NewCellRendererText(), "text", 0))
|
|
o.profiles_list.AppendColumn(gtk.NewTreeViewColumnWithAttributes(ctx.Translator.Translate("Urban Terror version", nil), gtk.NewCellRendererText(), "text", 1))
|
|
|
|
// Profiles list buttons.
|
|
urt_profiles_buttons_vbox := gtk.NewVBox(false, 0)
|
|
|
|
button_add := gtk.NewButtonWithLabel(ctx.Translator.Translate("Add", nil))
|
|
button_add.SetTooltipText(ctx.Translator.Translate("Add new profile", nil))
|
|
button_add.Clicked(o.addProfile)
|
|
urt_profiles_buttons_vbox.PackStart(button_add, false, true, 0)
|
|
|
|
button_edit := gtk.NewButtonWithLabel(ctx.Translator.Translate("Edit", nil))
|
|
button_edit.SetTooltipText(ctx.Translator.Translate("Edit selected profile. Do nothing if no profile was selected.", nil))
|
|
button_edit.Clicked(o.editProfile)
|
|
urt_profiles_buttons_vbox.PackStart(button_edit, false, true, 5)
|
|
|
|
// Spacer for profiles list buttons.
|
|
sep := gtk.NewVBox(false, 0)
|
|
urt_profiles_buttons_vbox.PackStart(sep, true, true, 5)
|
|
|
|
button_delete := gtk.NewButtonWithLabel(ctx.Translator.Translate("Delete", nil))
|
|
button_delete.SetTooltipText(ctx.Translator.Translate("Delete selected profile. Do nothing if no profile was selected.", nil))
|
|
button_delete.Clicked(o.deleteProfile)
|
|
urt_profiles_buttons_vbox.PackStart(button_delete, false, true, 0)
|
|
|
|
urt_hbox.Add(urt_profiles_buttons_vbox)
|
|
|
|
o.tab_widget.AppendPage(urt_hbox, gtk.NewLabel(ctx.Translator.Translate("Urban Terror", nil)))
|
|
|
|
// Load Profiles.
|
|
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
|
}
|
|
|
|
func (o *OptionsDialog) loadProfiles(data map[string]string) {
|
|
fmt.Println("Loading profiles...")
|
|
o.profiles_list_store.Clear()
|
|
|
|
for _, p := range ctx.Cache.Profiles {
|
|
var iter gtk.TreeIter
|
|
o.profiles_list_store.Append(&iter)
|
|
o.profiles_list_store.Set(&iter, 0, p.Profile.Name)
|
|
o.profiles_list_store.Set(&iter, 1, p.Profile.Version)
|
|
}
|
|
}
|
|
|
|
func (o *OptionsDialog) saveAppearance() {
|
|
ctx.Cfg.Cfg["/general/language"] = ctx.Translator.AcceptedLanguages[o.language_combo.GetActiveText()]
|
|
}
|
|
|
|
func (o *OptionsDialog) saveGeneral() {
|
|
if o.show_tray_icon.GetActive() {
|
|
ctx.Cfg.Cfg["/general/show_tray_icon"] = "1"
|
|
} else {
|
|
ctx.Cfg.Cfg["/general/show_tray_icon"] = "0"
|
|
}
|
|
|
|
if o.autoupdate.GetActive() {
|
|
ctx.Cfg.Cfg["/general/urtrator_autoupdate"] = "1"
|
|
} else {
|
|
ctx.Cfg.Cfg["/general/urtrator_autoupdate"] = "0"
|
|
}
|
|
|
|
// Servers updating tab.
|
|
master_server_addr := o.master_server_addr.GetText()
|
|
if len(master_server_addr) < 1 {
|
|
ctx.Cfg.Cfg["/servers_updating/master_server"] = "master.urbanterror.info:27900"
|
|
} else {
|
|
ctx.Cfg.Cfg["/servers_updating/master_server"] = master_server_addr
|
|
}
|
|
|
|
if o.servers_autoupdate.GetActive() {
|
|
ctx.Cfg.Cfg["/servers_updating/servers_autoupdate"] = "1"
|
|
} else {
|
|
ctx.Cfg.Cfg["/servers_updating/servers_autoupdate"] = "0"
|
|
}
|
|
|
|
update_timeout := o.servers_autoupdate_timeout.GetText()
|
|
if len(update_timeout) < 1 {
|
|
ctx.Cfg.Cfg["/servers_updating/servers_autoupdate_timeout"] = "10"
|
|
} else {
|
|
ctx.Cfg.Cfg["/servers_updating/servers_autoupdate_timeout"] = update_timeout
|
|
}
|
|
|
|
ctx.Eventer.LaunchEvent("initializeTasksForMainWindow", map[string]string{})
|
|
}
|
|
|
|
func (o *OptionsDialog) ShowOptionsDialog() {
|
|
o.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
|
|
o.window.SetTitle(ctx.Translator.Translate("URTrator - Options", nil))
|
|
o.window.Connect("destroy", o.closeOptionsDialogWithDiscard)
|
|
o.window.SetModal(true)
|
|
o.window.SetSizeRequest(550, 400)
|
|
o.window.SetPosition(gtk.WIN_POS_CENTER)
|
|
o.window.SetIcon(logo)
|
|
|
|
o.vbox = gtk.NewVBox(false, 0)
|
|
|
|
o.initializeTabs()
|
|
o.fill()
|
|
|
|
o.window.Add(o.vbox)
|
|
|
|
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
|
|
|
o.window.ShowAll()
|
|
}
|