Stability fixes, profile path and more.

Fixed a bunch of data races which should lead in stability improvements.

Added possibility to specify game profile path within profile item.

Added Urban Terror 4.3.2.
This commit is contained in:
Stanislav Nikitin 2017-05-08 23:38:54 +05:00
parent 1836c46d66
commit 1e676437d8
15 changed files with 136 additions and 32 deletions

View File

@ -44,9 +44,7 @@ func (c *Cache) deleteProfile(data map[string]string) {
_, ok1 := c.Profiles[data["profile_name"]] _, ok1 := c.Profiles[data["profile_name"]]
if !ok1 { if !ok1 {
fmt.Println("Profile deleted") fmt.Println("Profile deleted")
Database.Unlock()
Database.Db.MustExec(Database.Db.Rebind("DELETE FROM urt_profiles WHERE name=?"), data["profile_name"]) Database.Db.MustExec(Database.Db.Rebind("DELETE FROM urt_profiles WHERE name=?"), data["profile_name"])
Database.Lock()
} else { } else {
fmt.Println("Something goes wrong! Profile is still here!") fmt.Println("Something goes wrong! Profile is still here!")
} }
@ -81,7 +79,6 @@ func (c *Cache) FlushProfiles(data map[string]string) {
} }
} }
Database.Unlock()
tx := Database.Db.MustBegin() tx := Database.Db.MustBegin()
fmt.Println("Adding new profiles...") fmt.Println("Adding new profiles...")
for _, profile := range new_profiles { for _, profile := range new_profiles {
@ -92,7 +89,6 @@ func (c *Cache) FlushProfiles(data map[string]string) {
tx.NamedExec("UPDATE urt_profiles SET name=:name, version=:version, binary=:binary, second_x_session=:second_x_session, additional_parameters=:additional_parameters WHERE name=:name", &profile) tx.NamedExec("UPDATE urt_profiles SET name=:name, version=:version, binary=:binary, second_x_session=:second_x_session, additional_parameters=:additional_parameters WHERE name=:name", &profile)
} }
tx.Commit() tx.Commit()
Database.Lock()
fmt.Println("Done") fmt.Println("Done")
} }

View File

@ -89,7 +89,6 @@ func (c *Cache) FlushServers(data map[string]string) {
} }
} }
Database.Unlock()
tx := Database.Db.MustBegin() tx := Database.Db.MustBegin()
fmt.Println("Adding new servers...") fmt.Println("Adding new servers...")
if len(new_servers) > 0 { if len(new_servers) > 0 {
@ -106,7 +105,6 @@ func (c *Cache) FlushServers(data map[string]string) {
} }
tx.Commit() tx.Commit()
Database.Lock()
fmt.Println("Done") fmt.Println("Done")
} }

View File

@ -17,4 +17,5 @@ const (
var SUPPORTED_URT_VERSIONS []string = []string{ var SUPPORTED_URT_VERSIONS []string = []string{
"4.2.023", "4.2.023",
"4.3.1", "4.3.1",
"4.3.2",
} }

View File

@ -31,6 +31,9 @@ func (c *Config) initializePathsMac() {
fmt.Println("Will use data path: " + data_path) fmt.Println("Will use data path: " + data_path)
c.TEMP["DATA"] = data_path c.TEMP["DATA"] = data_path
profile_path := path.Join(home_path, "Library", "Application Support", "Quake3", "q3ut4")
c.TEMP["DEFAULT_PROFILE_PATH"] = profile_path
if _, err := os.Stat(data_path); os.IsNotExist(err) { if _, err := os.Stat(data_path); os.IsNotExist(err) {
os.MkdirAll(data_path, 0755) os.MkdirAll(data_path, 0755)
} }
@ -46,6 +49,9 @@ func (c *Config) initializePathsNix() {
fmt.Println("Will use data path: " + data_path) fmt.Println("Will use data path: " + data_path)
c.TEMP["DATA"] = data_path c.TEMP["DATA"] = data_path
profile_path := path.Join(home_path, ".q3a", "q3ut4")
c.TEMP["DEFAULT_PROFILE_PATH"] = profile_path
if _, err := os.Stat(data_path); os.IsNotExist(err) { if _, err := os.Stat(data_path); os.IsNotExist(err) {
os.MkdirAll(data_path, 0755) os.MkdirAll(data_path, 0755)
} }
@ -58,6 +64,10 @@ func (c *Config) initializePathsWin() {
data_path := path.Join(homedrive, homepath_without_drive, "AppData", "Roaming", "URTrator") data_path := path.Join(homedrive, homepath_without_drive, "AppData", "Roaming", "URTrator")
c.TEMP["DATA"] = data_path c.TEMP["DATA"] = data_path
// Verify it!
profile_path := path.Join(homedrive, homepath_without_drive, "AppData", "UrbanTerror43", "q3ut4")
c.TEMP["DEFAULT_PROFILE_PATH"] = profile_path
if _, err := os.Stat(data_path); os.IsNotExist(err) { if _, err := os.Stat(data_path); os.IsNotExist(err) {
os.MkdirAll(data_path, 0755) os.MkdirAll(data_path, 0755)
} }

View File

@ -49,11 +49,13 @@ func (d *Database) Close() {
tx.Commit() tx.Commit()
d.Db.Close() d.Db.Close()
runtime.UnlockOSThread() runtime.UnlockOSThread()
} }
func (d *Database) Initialize(cfg *configuration.Config) { func (d *Database) Initialize(cfg *configuration.Config) {
fmt.Println("Initializing database...") fmt.Println("Initializing database...")
runtime.LockOSThread() runtime.LockOSThread()
// Connect to database. // Connect to database.
@ -75,10 +77,6 @@ func (d *Database) Initialize(cfg *configuration.Config) {
} }
} }
func (d *Database) Lock() {
runtime.LockOSThread()
}
func (d *Database) Migrate() { func (d *Database) Migrate() {
// Getting current database version. // Getting current database version.
dbver := 0 dbver := 0
@ -94,7 +92,3 @@ func (d *Database) Migrate() {
migrate_full(d, dbver) migrate_full(d, dbver)
} }
func (d *Database) Unlock() {
runtime.UnlockOSThread()
}

View File

@ -49,6 +49,7 @@ func migrate_full(db *Database, version int) {
if version == 7 {seven_to_eight(db); version = 8} if version == 7 {seven_to_eight(db); version = 8}
if version == 8 {eight_to_nine(db); version = 9} if version == 8 {eight_to_nine(db); version = 9}
if version == 9 {nine_to_ten(db); version = 10} if version == 9 {nine_to_ten(db); version = 10}
if version == 10 {ten_to_eleven(db); version = 11}
} }
// Initial database structure. // Initial database structure.
@ -123,3 +124,10 @@ func nine_to_ten(db *Database) {
db.Db.MustExec("ALTER TABLE servers ADD bots VARCHAR(2) NOT NULL DEFAULT '0'") db.Db.MustExec("ALTER TABLE servers ADD bots VARCHAR(2) NOT NULL DEFAULT '0'")
db.Db.MustExec("UPDATE database SET version=10") db.Db.MustExec("UPDATE database SET version=10")
} }
// Urban terror's profile path.
func ten_to_eleven(db *Database) {
fmt.Println("Upgrading database from 10 to 11...")
db.Db.MustExec("ALTER TABLE urt_profiles ADD profile_path VARCHAR(4096) NOT NULL DEFAULT '~/.q3ut4'")
db.Db.MustExec("UPDATE database SET version=11")
}

View File

@ -20,4 +20,6 @@ type Profile struct {
Second_x_session string `db:"second_x_session"` Second_x_session string `db:"second_x_session"`
// Additional game parameters we will pass. // Additional game parameters we will pass.
Additional_params string `db:"additional_parameters"` Additional_params string `db:"additional_parameters"`
// Profile path.
Profile_path string `db:"profile_path"`
} }

View File

@ -17,6 +17,7 @@ import (
// github // github
"github.com/mattn/go-gtk/glib" "github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
) )
type Eventer struct { type Eventer struct {
@ -55,6 +56,14 @@ func (e *Eventer) LaunchEvent(event string, data map[string]string) error {
return false return false
}) })
for {
if gtk.EventsPending() {
gtk.MainIteration()
} else {
break
}
}
return nil return nil
} }

View File

@ -45,7 +45,9 @@ func (p *Pooler) Initialize() {
func (p *Pooler) PingOneServer(server_address string) { func (p *Pooler) PingOneServer(server_address string) {
var wait sync.WaitGroup var wait sync.WaitGroup
Cache.ServersMutex.Lock()
server := Cache.Servers[server_address].Server server := Cache.Servers[server_address].Server
Cache.ServersMutex.Unlock()
wait.Add(1) wait.Add(1)
go func(srv *datamodels.Server) { go func(srv *datamodels.Server) {
@ -63,6 +65,7 @@ func (p *Pooler) PingServers(servers_type string) {
cur_requests := 0 cur_requests := 0
var wait sync.WaitGroup var wait sync.WaitGroup
Cache.ServersMutex.Lock()
for _, server_to_ping := range Cache.Servers { for _, server_to_ping := range Cache.Servers {
if servers_type == "favorites" && server_to_ping.Server.Favorite != "1" { if servers_type == "favorites" && server_to_ping.Server.Favorite != "1" {
continue continue
@ -90,6 +93,7 @@ func (p *Pooler) PingServers(servers_type string) {
}(server_to_ping.Server) }(server_to_ping.Server)
} }
wait.Wait() wait.Wait()
Cache.ServersMutex.Unlock()
} }
func (p *Pooler) pingServersExecutor(server *datamodels.Server) error { func (p *Pooler) pingServersExecutor(server *datamodels.Server) error {
@ -132,7 +136,9 @@ func (p *Pooler) pingServersExecutor(server *datamodels.Server) error {
func (p *Pooler) UpdateOneServer(server_address string) { func (p *Pooler) UpdateOneServer(server_address string) {
var wait sync.WaitGroup var wait sync.WaitGroup
Cache.ServersMutex.Lock()
server := Cache.Servers[server_address].Server server := Cache.Servers[server_address].Server
Cache.ServersMutex.Unlock()
wait.Add(1) wait.Add(1)
go func(server *datamodels.Server) { go func(server *datamodels.Server) {
@ -151,6 +157,7 @@ func (p *Pooler) UpdateOneServer(server_address string) {
func (p *Pooler) UpdateServers(servers_type string) { func (p *Pooler) UpdateServers(servers_type string) {
var wait sync.WaitGroup var wait sync.WaitGroup
Cache.ServersMutex.Lock()
for _, server := range Cache.Servers { for _, server := range Cache.Servers {
if servers_type == "favorites" && server.Server.Favorite != "1" { if servers_type == "favorites" && server.Server.Favorite != "1" {
continue continue
@ -162,6 +169,7 @@ func (p *Pooler) UpdateServers(servers_type string) {
}(server.Server) }(server.Server)
} }
wait.Wait() wait.Wait()
Cache.ServersMutex.Unlock()
p.PingServers(servers_type) p.PingServers(servers_type)
Eventer.LaunchEvent("flushServers", map[string]string{}) Eventer.LaunchEvent("flushServers", map[string]string{})

View File

@ -77,12 +77,14 @@ func (t *Timer) executeTasks() {
} }
func (t *Timer) GetTaskStatus(task_name string) bool { func (t *Timer) GetTaskStatus(task_name string) bool {
_, ok := t.tasks[task_name] t.tasksMutex.Lock()
task, ok := t.tasks[task_name]
t.tasksMutex.Unlock()
if !ok { if !ok {
return false return false
} }
return t.tasks[task_name].InProgress return task.InProgress
} }
func (t *Timer) Initialize() { func (t *Timer) Initialize() {
@ -105,7 +107,9 @@ func (t *Timer) initializeStorage() {
} }
func (t *Timer) RemoveTask(task_name string) { func (t *Timer) RemoveTask(task_name string) {
t.tasksMutex.Lock()
_, ok := t.tasks[task_name] _, ok := t.tasks[task_name]
t.tasksMutex.Unlock()
if !ok { if !ok {
return return
} }
@ -116,10 +120,12 @@ func (t *Timer) RemoveTask(task_name string) {
} }
func (t *Timer) SetTaskNotInProgress(data map[string]string) { func (t *Timer) SetTaskNotInProgress(data map[string]string) {
t.tasksMutex.Lock()
_, ok := t.tasks[data["task_name"]] _, ok := t.tasks[data["task_name"]]
if !ok { if !ok {
return return
} }
t.tasks[data["task_name"]].InProgress = false t.tasks[data["task_name"]].InProgress = false
t.tasksMutex.Unlock()
} }

View File

@ -28,7 +28,7 @@ import (
"os" "os"
) )
// Detect language on Unices. // Detect language on Windows.
func (t *Translator) detectLanguage() { func (t *Translator) detectLanguage() {
fmt.Println("ToDo! Forcing en_US for now!") fmt.Println("ToDo! Forcing en_US for now!")
t.Language = "en_US" t.Language = "en_US"

View File

@ -153,6 +153,10 @@ type MainWindow struct {
// Used when user changed active tab, to show information about // Used when user changed active tab, to show information about
// server which is selected on activated tab. // server which is selected on activated tab.
use_other_servers_tab bool use_other_servers_tab bool
// Does servers updating already in progress?
// This helps to prevent random crashes when more than one
// updating process in progress.
servers_already_updating bool
} }
func (m *MainWindow) addToFavorites() { func (m *MainWindow) addToFavorites() {
@ -617,6 +621,8 @@ func (m *MainWindow) serversUpdateCompleted(data map[string]string) {
m.fav_servers.Emit("cursor-changed") m.fav_servers.Emit("cursor-changed")
} }
m.servers_already_updating = false
} }
func (m *MainWindow) setQuickConnectDetails(data map[string]string) { func (m *MainWindow) setQuickConnectDetails(data map[string]string) {
@ -628,8 +634,10 @@ func (m *MainWindow) setQuickConnectDetails(data map[string]string) {
func (m *MainWindow) setToolbarLabelText(data map[string]string) { func (m *MainWindow) setToolbarLabelText(data map[string]string) {
fmt.Println("Setting toolbar's label text...") fmt.Println("Setting toolbar's label text...")
if strings.Contains(data["text"], "<markup>") { if strings.Contains(data["text"], "<markup>") {
fmt.Println("With markup")
m.toolbar_label.SetMarkup(data["text"]) m.toolbar_label.SetMarkup(data["text"])
} else { } else {
fmt.Println("Without markup")
m.toolbar_label.SetLabel(data["text"]) m.toolbar_label.SetLabel(data["text"])
} }
} }
@ -792,6 +800,11 @@ func (m *MainWindow) unlockInterface() {
} }
func (m *MainWindow) updateOneServer() { func (m *MainWindow) updateOneServer() {
if m.servers_already_updating {
return
}
m.servers_already_updating = true
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Updating selected server...", nil) + "</span></markup>"}) ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Updating selected server...", nil) + "</span></markup>"})
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage())) current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
srv_address := m.getIpFromServersList(current_tab) srv_address := m.getIpFromServersList(current_tab)
@ -803,6 +816,11 @@ func (m *MainWindow) updateOneServer() {
// Triggered when "Update all servers" button is clicked. // Triggered when "Update all servers" button is clicked.
func (m *MainWindow) UpdateServers() { func (m *MainWindow) UpdateServers() {
if m.servers_already_updating {
return
}
m.servers_already_updating = true
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Updating servers...", nil) + "</span></markup>"}) ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Updating servers...", nil) + "</span></markup>"})
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage())) current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
fmt.Println("Updating servers on tab '" + current_tab + "'...") fmt.Println("Updating servers on tab '" + current_tab + "'...")

View File

@ -233,7 +233,7 @@ func (m *MainWindow) InitializeMainMenu() {
about_menu.Append(about_menu_sep1) about_menu.Append(about_menu_sep1)
// Drop databases thing. // Drop databases thing.
about_menu_drop_database_data_item := gtk.NewMenuItemWithMnemonic(ctx.Translator.Translate("Drop database data...", nil)) about_menu_drop_database_data_item := gtk.NewMenuItemWithMnemonic(ctx.Translator.Translate("Drop local caches and settings", nil))
about_menu.Append(about_menu_drop_database_data_item) about_menu.Append(about_menu_drop_database_data_item)
about_menu_drop_database_data_item.Connect("activate", m.dropDatabasesData) about_menu_drop_database_data_item.Connect("activate", m.dropDatabasesData)
} }
@ -335,6 +335,7 @@ func (m *MainWindow) initializeStorages() {
// Application isn't initialized. // Application isn't initialized.
m.initialized = false m.initialized = false
m.use_other_servers_tab = false m.use_other_servers_tab = false
m.servers_already_updating = false
// Gamemodes. // Gamemodes.
m.gamemodes = make(map[string]string) m.gamemodes = make(map[string]string)
m.gamemodes = map[string]string{ m.gamemodes = map[string]string{

View File

@ -194,7 +194,7 @@ func (o *OptionsDialog) initializeAppearanceTab() {
} }
o.language_combo.SetActive(lang_active) o.language_combo.SetActive(lang_active)
appearance_table.Attach(o.language_combo, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5) appearance_table.Attach(o.language_combo, 1, 2, 0, 1, gtk.FILL | gtk.EXPAND, gtk.FILL, 5, 5)
appearance_vbox.PackStart(appearance_table, false, true, 0) appearance_vbox.PackStart(appearance_table, false, true, 0)
o.tab_widget.AppendPage(appearance_vbox, gtk.NewLabel(ctx.Translator.Translate("Appearance", nil))) o.tab_widget.AppendPage(appearance_vbox, gtk.NewLabel(ctx.Translator.Translate("Appearance", nil)))
@ -212,7 +212,7 @@ func (o *OptionsDialog) initializeGeneralTab() {
o.show_tray_icon = gtk.NewCheckButtonWithLabel("") o.show_tray_icon = gtk.NewCheckButtonWithLabel("")
o.show_tray_icon.SetTooltipText(ctx.Translator.Translate("Show icon in tray", nil)) 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) general_table.Attach(o.show_tray_icon, 1, 2, 0, 1, gtk.FILL | gtk.EXPAND, gtk.FILL, 5, 5)
// Autoupdate checkbox. // Autoupdate checkbox.
autoupdate_tooltip := ctx.Translator.Translate("Should URTrator check for updates and update itself? Not working now.", nil) autoupdate_tooltip := ctx.Translator.Translate("Should URTrator check for updates and update itself? Not working now.", nil)
@ -223,7 +223,7 @@ func (o *OptionsDialog) initializeGeneralTab() {
o.autoupdate = gtk.NewCheckButtonWithLabel("") o.autoupdate = gtk.NewCheckButtonWithLabel("")
o.autoupdate.SetTooltipText(autoupdate_tooltip) o.autoupdate.SetTooltipText(autoupdate_tooltip)
general_table.Attach(o.autoupdate, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5) general_table.Attach(o.autoupdate, 1, 2, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL, 5, 5)
// Vertical separator. // Vertical separator.
sep := gtk.NewVBox(false, 0) sep := gtk.NewVBox(false, 0)
@ -260,7 +260,7 @@ func (o *OptionsDialog) initializeServersOptionsTab() {
o.servers_autoupdate = gtk.NewCheckButtonWithLabel("") o.servers_autoupdate = gtk.NewCheckButtonWithLabel("")
o.servers_autoupdate.SetTooltipText(servers_autoupdate_cb_tooptip) 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_updating_table.Attach(o.servers_autoupdate, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL, 5, 5)
// Servers update timeout. // Servers update timeout.
servers_autoupdate_timeout_tooltip := ctx.Translator.Translate("Timeout which will trigger servers information update, in minutes.", nil) servers_autoupdate_timeout_tooltip := ctx.Translator.Translate("Timeout which will trigger servers information update, in minutes.", nil)
@ -417,7 +417,7 @@ func (o *OptionsDialog) ShowOptionsDialog() {
o.window.SetTitle(ctx.Translator.Translate("URTrator - Options", nil)) o.window.SetTitle(ctx.Translator.Translate("URTrator - Options", nil))
o.window.Connect("destroy", o.closeOptionsDialogWithDiscard) o.window.Connect("destroy", o.closeOptionsDialogWithDiscard)
o.window.SetModal(true) o.window.SetModal(true)
o.window.SetSizeRequest(550, 400) o.window.SetSizeRequest(750, 600)
o.window.SetPosition(gtk.WIN_POS_CENTER) o.window.SetPosition(gtk.WIN_POS_CENTER)
o.window.SetIcon(logo) o.window.SetIcon(logo)

View File

@ -33,6 +33,8 @@ type OptionsProfile struct {
profile_name *gtk.Entry profile_name *gtk.Entry
// Binary path. // Binary path.
binary_path *gtk.Entry binary_path *gtk.Entry
// Profile directory path.
profile_path *gtk.Entry
// Urban Terror versions combobox // Urban Terror versions combobox
urt_version_combo *gtk.ComboBoxText urt_version_combo *gtk.ComboBoxText
// Another X session? // Another X session?
@ -42,6 +44,8 @@ type OptionsProfile struct {
// File chooser dialog for selecting binary. // File chooser dialog for selecting binary.
f *gtk.FileChooserDialog f *gtk.FileChooserDialog
// Profile directory chooser dialog.
p *gtk.FileChooserDialog
// Flags. // Flags.
// This is profile update? // This is profile update?
@ -58,6 +62,15 @@ func (op *OptionsProfile) browseForBinary() {
op.f.Run() op.f.Run()
} }
func (op *OptionsProfile) browseForProfile() {
op.p = gtk.NewFileChooserDialog(ctx.Translator.Translate("URTrator - Select Urban Terror profile path", nil), op.window, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
op.p.Response(op.browseForProfileHelper)
if op.profile_path.GetText() != "" {
op.p.SetCurrentFolder(op.profile_path.GetText())
}
op.p.Run()
}
func (op *OptionsProfile) browseForBinaryHelper() { func (op *OptionsProfile) browseForBinaryHelper() {
filename := op.f.GetFilename() filename := op.f.GetFilename()
op.binary_path.SetText(filename) op.binary_path.SetText(filename)
@ -122,6 +135,16 @@ func (op *OptionsProfile) browseForBinaryHelper() {
} }
} }
} }
if op.profile_path.GetText() == "" {
op.profile_path.SetText(ctx.Cfg.TEMP["DEFAULT_PROFILE_PATH"])
}
}
func (op *OptionsProfile) browseForProfileHelper() {
directory := op.p.GetFilename()
op.profile_path.SetText(directory)
op.p.Destroy()
} }
func (op *OptionsProfile) closeByCancel() { func (op *OptionsProfile) closeByCancel() {
@ -148,7 +171,7 @@ func (op *OptionsProfile) Initialize(update bool) {
op.window.SetPosition(gtk.WIN_POS_CENTER) op.window.SetPosition(gtk.WIN_POS_CENTER)
op.window.SetIcon(logo) op.window.SetIcon(logo)
op.table = gtk.NewTable(6, 2, false) op.table = gtk.NewTable(7, 2, false)
op.table.SetRowSpacings(2) op.table.SetRowSpacings(2)
// Profile name. // Profile name.
@ -173,8 +196,8 @@ func (op *OptionsProfile) Initialize(update bool) {
op.urt_version_combo = gtk.NewComboBoxText() op.urt_version_combo = gtk.NewComboBoxText()
op.urt_version_combo.SetTooltipText(urt_version_tooltip) op.urt_version_combo.SetTooltipText(urt_version_tooltip)
op.urt_version_combo.AppendText("4.2.023") op.urt_version_combo.AppendText("4.2.023")
op.urt_version_combo.AppendText("4.3.0")
op.urt_version_combo.AppendText("4.3.1") op.urt_version_combo.AppendText("4.3.1")
op.urt_version_combo.AppendText("4.3.2")
op.urt_version_combo.SetActive(2) op.urt_version_combo.SetActive(2)
op.table.Attach(op.urt_version_combo, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5) op.table.Attach(op.urt_version_combo, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5)
@ -195,34 +218,53 @@ func (op *OptionsProfile) Initialize(update bool) {
binpath_hbox.PackStart(button_select_binary, false, true, 5) binpath_hbox.PackStart(button_select_binary, false, true, 5)
op.table.Attach(binpath_hbox, 1, 2, 2, 3, gtk.FILL, gtk.FILL, 0, 0) op.table.Attach(binpath_hbox, 1, 2, 2, 3, gtk.FILL, gtk.FILL, 0, 0)
// Path to Urban Terror's profile directory.
// Should be in user's home directory automatically, but can be
// changed :).
select_profile_path_tooltip := ctx.Translator.Translate("Urban Terror profile path.\n\nSpecify directory where configs, demos\nand downloaded maps are located.\n\nDefault: $HOME/.q3ut4", nil)
profile_path_hbox := gtk.NewHBox(false, 0)
profile_path_label := gtk.NewLabel(ctx.Translator.Translate("Profile path:", nil))
profile_path_label.SetTooltipText(select_profile_path_tooltip)
profile_path_label.SetAlignment(0, 0)
op.table.Attach(profile_path_label, 0, 1, 3, 4, gtk.FILL, gtk.SHRINK, 5, 5)
op.profile_path = gtk.NewEntry()
op.profile_path.SetTooltipText(select_profile_path_tooltip)
button_select_path := gtk.NewButtonWithLabel(ctx.Translator.Translate("Browse", nil))
button_select_path.SetTooltipText(select_profile_path_tooltip)
button_select_path.Clicked(op.browseForProfile)
profile_path_hbox.PackStart(op.profile_path, true, true, 5)
profile_path_hbox.PackStart(button_select_path, false, true, 5)
op.table.Attach(profile_path_hbox, 1, 2, 3, 4, gtk.FILL, gtk.FILL, 0, 0)
// Should we use additional X session? // Should we use additional X session?
another_x_tooltip := ctx.Translator.Translate("If this is checked, Urban Terror will be launched in another X session.\n\nThis could help if you're experiencing visual lag, glitches and FPS drops under compositing WMs, like Mutter and KWin.", nil) another_x_tooltip := ctx.Translator.Translate("If this is checked, Urban Terror will be launched in another X session.\n\nThis could help if you're experiencing visual lag, glitches and FPS drops under compositing WMs, like Mutter and KWin.", nil)
another_x_label := gtk.NewLabel(ctx.Translator.Translate("Start Urban Terror in another X session?", nil)) another_x_label := gtk.NewLabel(ctx.Translator.Translate("Start Urban Terror in another X session?", nil))
another_x_label.SetTooltipText(another_x_tooltip) another_x_label.SetTooltipText(another_x_tooltip)
another_x_label.SetAlignment(0, 0) another_x_label.SetAlignment(0, 0)
op.table.Attach(another_x_label, 0, 1, 3, 4, gtk.FILL, gtk.SHRINK, 5, 5) op.table.Attach(another_x_label, 0, 1, 4, 5, gtk.FILL, gtk.SHRINK, 5, 5)
op.another_x_session = gtk.NewCheckButtonWithLabel("") op.another_x_session = gtk.NewCheckButtonWithLabel("")
op.another_x_session.SetTooltipText(another_x_tooltip) op.another_x_session.SetTooltipText(another_x_tooltip)
// macOS and Windows can't do that :). // macOS and Windows can't do that :).
if runtime.GOOS != "linux" { if runtime.GOOS != "linux" {
op.another_x_session.SetSensitive(false) op.another_x_session.SetSensitive(false)
} }
op.table.Attach(op.another_x_session, 1, 2, 3, 4, gtk.FILL, gtk.FILL, 5, 5) op.table.Attach(op.another_x_session, 1, 2, 4, 5, gtk.FILL, gtk.FILL, 5, 5)
// Additional game parameters. // Additional game parameters.
params_tooltip := ctx.Translator.Translate("Additional parameters that will be passed to Urban Terror executable.", nil) params_tooltip := ctx.Translator.Translate("Additional parameters that will be passed to Urban Terror executable.", nil)
params_label := gtk.NewLabel(ctx.Translator.Translate("Additional parameters:", nil)) params_label := gtk.NewLabel(ctx.Translator.Translate("Additional parameters:", nil))
params_label.SetTooltipText(params_tooltip) params_label.SetTooltipText(params_tooltip)
params_label.SetAlignment(0, 0) params_label.SetAlignment(0, 0)
op.table.Attach(params_label, 0, 1, 4, 5, gtk.FILL, gtk.SHRINK, 5, 5) op.table.Attach(params_label, 0, 1, 5, 6, gtk.FILL, gtk.SHRINK, 5, 5)
op.additional_parameters = gtk.NewEntry() op.additional_parameters = gtk.NewEntry()
op.additional_parameters.SetTooltipText(params_tooltip) op.additional_parameters.SetTooltipText(params_tooltip)
op.table.Attach(op.additional_parameters, 1, 2, 4, 5, gtk.FILL, gtk.FILL, 5, 5) op.table.Attach(op.additional_parameters, 1, 2, 5, 6, gtk.FILL, gtk.FILL, 5, 5)
// Invisible thing. // Invisible thing.
inv_label := gtk.NewLabel("") inv_label := gtk.NewLabel("")
op.table.Attach(inv_label, 1, 2, 5, 6, gtk.EXPAND, gtk.FILL, 5, 5) op.table.Attach(inv_label, 1, 2, 6, 7, gtk.EXPAND, gtk.FILL, 5, 5)
// The buttons. // The buttons.
buttons_box := gtk.NewHBox(false, 0) buttons_box := gtk.NewHBox(false, 0)
@ -266,13 +308,18 @@ func (op *OptionsProfile) InitializeUpdate(profile_name string) {
op.profile_name.SetText(profile.Name) op.profile_name.SetText(profile.Name)
op.binary_path.SetText(profile.Binary) op.binary_path.SetText(profile.Binary)
op.additional_parameters.SetText(profile.Additional_params) op.additional_parameters.SetText(profile.Additional_params)
if profile.Profile_path == "" {
op.profile_path.SetText(ctx.Cfg.TEMP["DEFAULT_PROFILE_PATH"])
} else {
op.profile_path.SetText(profile.Profile_path)
}
if profile.Second_x_session == "1" { if profile.Second_x_session == "1" {
op.another_x_session.SetActive(true) op.another_x_session.SetActive(true)
} }
if profile.Version == "4.3.0" { if profile.Version == "4.3.1" {
op.urt_version_combo.SetActive(1) op.urt_version_combo.SetActive(1)
} else if profile.Version == "4.3.1" { } else if profile.Version == "4.3.2" {
op.urt_version_combo.SetActive(2) op.urt_version_combo.SetActive(2)
} else { } else {
op.urt_version_combo.SetActive(0) op.urt_version_combo.SetActive(0)
@ -333,6 +380,12 @@ func (op *OptionsProfile) saveProfile() {
ctx.Cache.Profiles[profile_name].Profile.Binary = op.binary_path.GetText() ctx.Cache.Profiles[profile_name].Profile.Binary = op.binary_path.GetText()
ctx.Cache.Profiles[profile_name].Profile.Additional_params = op.additional_parameters.GetText() ctx.Cache.Profiles[profile_name].Profile.Additional_params = op.additional_parameters.GetText()
if op.profile_path.GetText() == "" {
ctx.Cache.Profiles[profile_name].Profile.Profile_path = "~/.q3ut4"
} else {
ctx.Cache.Profiles[profile_name].Profile.Profile_path = op.profile_path.GetText()
}
if op.another_x_session.GetActive() { if op.another_x_session.GetActive() {
ctx.Cache.Profiles[profile_name].Profile.Second_x_session = "1" ctx.Cache.Profiles[profile_name].Profile.Second_x_session = "1"
} else { } else {