One more huge refactoring and quick connect widget working.

Refactored the way URTrator working with profiles - now everything
that could be taken from internal cache will be taken from cache.
The very same as with servers.

Moved all callbacks from callbacks to events, so we achieve full
asynchronity here and can launch anything in goroutines :).

Moved MainWindow-related game launching functions into another
file (mainwindow_launch.go).

Made quick connect widget working. Note, that even if you're on
Favorites and trying to connect to one of favorited servers but
with quick connect - you still have to choose right profile
near Launch button!

Maybe something else I forget.
This commit is contained in:
Stanislav Nikitin 2016-10-08 19:57:33 +05:00
parent 4421e29695
commit e2a9298f85
14 changed files with 587 additions and 371 deletions

127
cache/cache_object.go vendored
View File

@ -15,140 +15,31 @@ import (
// local // local
"github.com/pztrn/urtrator/cachemodels" "github.com/pztrn/urtrator/cachemodels"
"github.com/pztrn/urtrator/datamodels"
) )
type Cache struct { type Cache struct {
// Profiles cache.
Profiles map[string]*cachemodels.Profile
// Servers cache. // Servers cache.
Servers map[string]*cachemodels.Server Servers map[string]*cachemodels.Server
} }
func (c *Cache) CreateServer(addr string) {
_, ok := c.Servers[addr]
if !ok {
c.Servers[addr] = &cachemodels.Server{}
c.Servers[addr].Server = &datamodels.Server{}
} else {
fmt.Println("Server " + addr + " already exist.")
}
}
// Flush servers to database.
func (c *Cache) FlushServers() {
fmt.Println("Updating servers information in database...")
raw_cached := []datamodels.Server{}
Database.Db.Select(&raw_cached, "SELECT * FROM servers")
// Create map[string]*datamodels.Server once, so we won't iterate
// over slice of datamodels.Server everytime.
cached_servers := make(map[string]*datamodels.Server)
for s := range raw_cached {
mapping_item_name := raw_cached[s].Ip + ":" + raw_cached[s].Port
cached_servers[mapping_item_name] = &raw_cached[s]
}
new_servers := make(map[string]*datamodels.Server)
// Update our cached mapping.
for _, s := range c.Servers {
mapping_item_name := s.Server.Ip + ":" + s.Server.Port
_, ok := cached_servers[mapping_item_name]
if !ok {
fmt.Println(mapping_item_name + " not found!")
new_servers[mapping_item_name] = &datamodels.Server{}
new_servers[mapping_item_name].Ip = s.Server.Ip
new_servers[mapping_item_name].Port = s.Server.Port
new_servers[mapping_item_name].Name = s.Server.Name
new_servers[mapping_item_name].Players = s.Server.Players
new_servers[mapping_item_name].Maxplayers = s.Server.Maxplayers
new_servers[mapping_item_name].Ping = s.Server.Ping
new_servers[mapping_item_name].Map = s.Server.Map
new_servers[mapping_item_name].Gamemode = s.Server.Gamemode
new_servers[mapping_item_name].Version = s.Server.Version
new_servers[mapping_item_name].ExtendedConfig = s.Server.ExtendedConfig
new_servers[mapping_item_name].PlayersInfo = s.Server.PlayersInfo
new_servers[mapping_item_name].IsPrivate = s.Server.IsPrivate
} else {
cached_servers[mapping_item_name].Ip = s.Server.Ip
cached_servers[mapping_item_name].Port = s.Server.Port
cached_servers[mapping_item_name].Name = s.Server.Name
cached_servers[mapping_item_name].Players = s.Server.Players
cached_servers[mapping_item_name].Maxplayers = s.Server.Maxplayers
cached_servers[mapping_item_name].Ping = s.Server.Ping
cached_servers[mapping_item_name].Map = s.Server.Map
cached_servers[mapping_item_name].Gamemode = s.Server.Gamemode
cached_servers[mapping_item_name].Version = s.Server.Version
cached_servers[mapping_item_name].ExtendedConfig = s.Server.ExtendedConfig
cached_servers[mapping_item_name].PlayersInfo = s.Server.PlayersInfo
cached_servers[mapping_item_name].IsPrivate = s.Server.IsPrivate
}
}
Database.Unlock()
tx := Database.Db.MustBegin()
fmt.Println("Adding new servers...")
if len(new_servers) > 0 {
for _, srv := range new_servers {
tx.NamedExec("INSERT INTO servers (ip, port, name, ping, players, maxplayers, gamemode, map, version, extended_config, players_info, is_private) VALUES (:ip, :port, :name, :ping, :players, :maxplayers, :gamemode, :map, :version, :extended_config, :players_info, :is_private)", srv)
}
}
fmt.Println("Updating cached servers...")
for _, srv := range cached_servers {
_, err := tx.NamedExec("UPDATE servers SET name=:name, players=:players, maxplayers=:maxplayers, gamemode=:gamemode, map=:map, ping=:ping, version=:version, extended_config=:extended_config, players_info=:players_info, is_private=:is_private WHERE ip=:ip AND port=:port", &srv)
if err != nil {
fmt.Println(err.Error())
}
}
tx.Commit()
Database.Lock()
fmt.Println("Done")
}
func (c *Cache) Initialize() { func (c *Cache) Initialize() {
fmt.Println("Initializing cache...") fmt.Println("Initializing cache...")
c.initializeStorages() c.initializeStorages()
c.LoadServers() c.LoadServers(map[string]string{})
Eventer.AddEventHandler("deleteProfile", c.deleteProfile)
Eventer.AddEventHandler("flushProfiles", c.FlushProfiles)
Eventer.AddEventHandler("loadProfiles", c.LoadProfiles)
Eventer.AddEventHandler("flushServers", c.FlushServers) Eventer.AddEventHandler("flushServers", c.FlushServers)
Eventer.AddEventHandler("loadServersIntoCache", c.LoadServers) Eventer.AddEventHandler("loadServersIntoCache", c.LoadServers)
} }
func (c *Cache) initializeStorages() { func (c *Cache) initializeStorages() {
// Profiles cache.
c.Profiles = make(map[string]*cachemodels.Profile)
// Servers cache. // Servers cache.
c.Servers = make(map[string]*cachemodels.Server) c.Servers = make(map[string]*cachemodels.Server)
} }
func (c *Cache) LoadServers() {
fmt.Println("Loading servers into cache...")
c.Servers = make(map[string]*cachemodels.Server)
// Getting servers from database.
raw_servers := []datamodels.Server{}
err := Database.Db.Select(&raw_servers, "SELECT * FROM servers")
if err != nil {
fmt.Println(err.Error())
}
// Due to nature of pointers and goroutines thing (?) this should
// be done in this way.
for _, server := range raw_servers {
key := server.Ip + ":" + server.Port
c.CreateServer(key)
c.Servers[key].Server.Name = server.Name
c.Servers[key].Server.Ip = server.Ip
c.Servers[key].Server.Port = server.Port
c.Servers[key].Server.Players = server.Players
c.Servers[key].Server.Maxplayers = server.Maxplayers
c.Servers[key].Server.Ping = server.Ping
c.Servers[key].Server.Gamemode = server.Gamemode
c.Servers[key].Server.Map = server.Map
c.Servers[key].Server.Version = server.Version
c.Servers[key].Server.Favorite = server.Favorite
c.Servers[key].Server.Password = server.Password
c.Servers[key].Server.ProfileToUse = server.ProfileToUse
c.Servers[key].Server.ExtendedConfig = server.ExtendedConfig
c.Servers[key].Server.PlayersInfo = server.PlayersInfo
c.Servers[key].Server.IsPrivate = server.IsPrivate
}
fmt.Println("Load completed.")
}

115
cache/cache_profiles.go vendored Normal file
View File

@ -0,0 +1,115 @@
// 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 cache
import (
// stdlib
"fmt"
"strconv"
// local
"github.com/pztrn/urtrator/cachemodels"
"github.com/pztrn/urtrator/datamodels"
)
func (c *Cache) CreateProfile(name string) {
fmt.Println("Creating profile " + name)
_, ok := c.Profiles[name]
if !ok {
c.Profiles[name] = &cachemodels.Profile{}
c.Profiles[name].Profile = &datamodels.Profile{}
}
}
func (c *Cache) deleteProfile(data map[string]string) {
fmt.Println("Deleting profile " + data["profile_name"])
_, ok := c.Profiles[data["profile_name"]]
if ok {
delete(c.Profiles, data["profile_name"])
}
_, ok1 := c.Profiles[data["profile_name"]]
if !ok1 {
fmt.Println("Profile deleted")
Database.Unlock()
Database.Db.MustExec(Database.Db.Rebind("DELETE FROM urt_profiles WHERE name=?"), data["profile_name"])
Database.Lock()
} else {
fmt.Println("Something goes wrong! Profile is still here!")
}
}
func (c *Cache) FlushProfiles(data map[string]string) {
fmt.Println("Flushing profiles to database...")
raw_profiles := []datamodels.Profile{}
err := Database.Db.Select(&raw_profiles, "SELECT * FROM urt_profiles")
if err != nil {
fmt.Println(err.Error())
}
cached_profiles := make(map[string]*datamodels.Profile)
for i := range raw_profiles {
cached_profiles[raw_profiles[i].Name] = &raw_profiles[i]
}
new_profiles := make(map[string]*datamodels.Profile)
for _, profile := range c.Profiles {
_, ok := cached_profiles[profile.Profile.Name]
if !ok {
fmt.Println("Flushing new profile " + profile.Profile.Name)
new_profiles[profile.Profile.Name] = &datamodels.Profile{}
new_profiles[profile.Profile.Name].Name = profile.Profile.Name
new_profiles[profile.Profile.Name].Version = profile.Profile.Version
new_profiles[profile.Profile.Name].Binary = profile.Profile.Binary
new_profiles[profile.Profile.Name].Second_x_session = profile.Profile.Second_x_session
new_profiles[profile.Profile.Name].Additional_params = profile.Profile.Additional_params
}
}
Database.Unlock()
tx := Database.Db.MustBegin()
fmt.Println("Adding new profiles...")
for _, profile := range new_profiles {
tx.NamedExec("INSERT INTO urt_profiles (name, version, binary, second_x_session, additional_parameters) VALUES (:name, :version, :binary, :second_x_session, :additional_parameters)", &profile)
}
fmt.Println("Updating existing profiles...")
for _, profile := range cached_profiles {
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()
Database.Lock()
fmt.Println("Done")
}
func (c *Cache) LoadProfiles(data map[string]string) {
fmt.Println("Loading profiles to cache...")
raw_profiles := []datamodels.Profile{}
err := Database.Db.Select(&raw_profiles, "SELECT * FROM urt_profiles")
if err != nil {
fmt.Println(err.Error())
}
for _, profile := range raw_profiles {
c.Profiles[profile.Name] = &cachemodels.Profile{}
c.Profiles[profile.Name].Profile = &datamodels.Profile{}
c.Profiles[profile.Name].Profile.Name = profile.Name
c.Profiles[profile.Name].Profile.Version = profile.Version
c.Profiles[profile.Name].Profile.Binary = profile.Binary
c.Profiles[profile.Name].Profile.Second_x_session = profile.Second_x_session
c.Profiles[profile.Name].Profile.Additional_params = profile.Additional_params
}
fmt.Println("Load completed. Loaded " + strconv.Itoa(len(c.Profiles)) + " profiles.")
}

135
cache/cache_servers.go vendored Normal file
View File

@ -0,0 +1,135 @@
// 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 cache
import (
// stdlib
"fmt"
// local
"github.com/pztrn/urtrator/cachemodels"
"github.com/pztrn/urtrator/datamodels"
)
func (c *Cache) CreateServer(addr string) {
_, ok := c.Servers[addr]
if !ok {
c.Servers[addr] = &cachemodels.Server{}
c.Servers[addr].Server = &datamodels.Server{}
} else {
fmt.Println("Server " + addr + " already exist.")
}
}
// Flush servers to database.
func (c *Cache) FlushServers(data map[string]string) {
fmt.Println("Updating servers information in database...")
raw_cached := []datamodels.Server{}
Database.Db.Select(&raw_cached, "SELECT * FROM servers")
// Create map[string]*datamodels.Server once, so we won't iterate
// over slice of datamodels.Server everytime.
cached_servers := make(map[string]*datamodels.Server)
for s := range raw_cached {
mapping_item_name := raw_cached[s].Ip + ":" + raw_cached[s].Port
cached_servers[mapping_item_name] = &raw_cached[s]
}
new_servers := make(map[string]*datamodels.Server)
// Update our cached mapping.
for _, s := range c.Servers {
mapping_item_name := s.Server.Ip + ":" + s.Server.Port
_, ok := cached_servers[mapping_item_name]
if !ok {
fmt.Println(mapping_item_name + " not found!")
new_servers[mapping_item_name] = &datamodels.Server{}
new_servers[mapping_item_name].Ip = s.Server.Ip
new_servers[mapping_item_name].Port = s.Server.Port
new_servers[mapping_item_name].Name = s.Server.Name
new_servers[mapping_item_name].Players = s.Server.Players
new_servers[mapping_item_name].Maxplayers = s.Server.Maxplayers
new_servers[mapping_item_name].Ping = s.Server.Ping
new_servers[mapping_item_name].Map = s.Server.Map
new_servers[mapping_item_name].Gamemode = s.Server.Gamemode
new_servers[mapping_item_name].Version = s.Server.Version
new_servers[mapping_item_name].ExtendedConfig = s.Server.ExtendedConfig
new_servers[mapping_item_name].PlayersInfo = s.Server.PlayersInfo
new_servers[mapping_item_name].IsPrivate = s.Server.IsPrivate
} else {
cached_servers[mapping_item_name].Ip = s.Server.Ip
cached_servers[mapping_item_name].Port = s.Server.Port
cached_servers[mapping_item_name].Name = s.Server.Name
cached_servers[mapping_item_name].Players = s.Server.Players
cached_servers[mapping_item_name].Maxplayers = s.Server.Maxplayers
cached_servers[mapping_item_name].Ping = s.Server.Ping
cached_servers[mapping_item_name].Map = s.Server.Map
cached_servers[mapping_item_name].Gamemode = s.Server.Gamemode
cached_servers[mapping_item_name].Version = s.Server.Version
cached_servers[mapping_item_name].ExtendedConfig = s.Server.ExtendedConfig
cached_servers[mapping_item_name].PlayersInfo = s.Server.PlayersInfo
cached_servers[mapping_item_name].IsPrivate = s.Server.IsPrivate
}
}
Database.Unlock()
tx := Database.Db.MustBegin()
fmt.Println("Adding new servers...")
if len(new_servers) > 0 {
for _, srv := range new_servers {
tx.NamedExec("INSERT INTO servers (ip, port, name, ping, players, maxplayers, gamemode, map, version, extended_config, players_info, is_private) VALUES (:ip, :port, :name, :ping, :players, :maxplayers, :gamemode, :map, :version, :extended_config, :players_info, :is_private)", srv)
}
}
fmt.Println("Updating cached servers...")
for _, srv := range cached_servers {
_, err := tx.NamedExec("UPDATE servers SET name=:name, players=:players, maxplayers=:maxplayers, gamemode=:gamemode, map=:map, ping=:ping, version=:version, extended_config=:extended_config, players_info=:players_info, is_private=:is_private WHERE ip=:ip AND port=:port", &srv)
if err != nil {
fmt.Println(err.Error())
}
}
tx.Commit()
Database.Lock()
fmt.Println("Done")
}
func (c *Cache) LoadServers(data map[string]string) {
fmt.Println("Loading servers into cache...")
c.Servers = make(map[string]*cachemodels.Server)
// Getting servers from database.
raw_servers := []datamodels.Server{}
err := Database.Db.Select(&raw_servers, "SELECT * FROM servers")
if err != nil {
fmt.Println(err.Error())
}
// Due to nature of pointers and goroutines thing (?) this should
// be done in this way.
for _, server := range raw_servers {
key := server.Ip + ":" + server.Port
c.CreateServer(key)
c.Servers[key].Server.Name = server.Name
c.Servers[key].Server.Ip = server.Ip
c.Servers[key].Server.Port = server.Port
c.Servers[key].Server.Players = server.Players
c.Servers[key].Server.Maxplayers = server.Maxplayers
c.Servers[key].Server.Ping = server.Ping
c.Servers[key].Server.Gamemode = server.Gamemode
c.Servers[key].Server.Map = server.Map
c.Servers[key].Server.Version = server.Version
c.Servers[key].Server.Favorite = server.Favorite
c.Servers[key].Server.Password = server.Password
c.Servers[key].Server.ProfileToUse = server.ProfileToUse
c.Servers[key].Server.ExtendedConfig = server.ExtendedConfig
c.Servers[key].Server.PlayersInfo = server.PlayersInfo
c.Servers[key].Server.IsPrivate = server.IsPrivate
}
fmt.Println("Load completed.")
}

19
cachemodels/profile.go Normal file
View File

@ -0,0 +1,19 @@
// 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 cachemodels
import (
// local
"github.com/pztrn/urtrator/datamodels"
)
type Profile struct {
Profile *datamodels.Profile
}

View File

@ -51,7 +51,8 @@ func (ctx *Context) Close() error {
if launched != nil { if launched != nil {
return errors.New("Urban Terror is launched!") return errors.New("Urban Terror is launched!")
} }
ctx.Cache.FlushServers() ctx.Cache.FlushProfiles(map[string]string{})
ctx.Cache.FlushServers(map[string]string{})
ctx.Database.Close() ctx.Database.Close()
// At last, close main window. // At last, close main window.

View File

@ -17,13 +17,13 @@ import (
type Eventer struct { type Eventer struct {
// Events // Events
events map[string]map[string]func() events map[string]map[string]func(data map[string]string)
} }
func (e *Eventer) AddEventHandler(event string, handler func()) { func (e *Eventer) AddEventHandler(event string, handler func(data map[string]string)) {
_, ok := e.events[event] _, ok := e.events[event]
if !ok { if !ok {
e.events[event] = make(map[string]func()) e.events[event] = make(map[string]func(data map[string]string))
} }
event_id_raw := make([]byte, 16) event_id_raw := make([]byte, 16)
crand.Read(event_id_raw) crand.Read(event_id_raw)
@ -36,10 +36,10 @@ func (e *Eventer) Initialize() {
} }
func (e *Eventer) initializeStorage() { func (e *Eventer) initializeStorage() {
e.events = make(map[string]map[string]func()) e.events = make(map[string]map[string]func(data map[string]string))
} }
func (e *Eventer) LaunchEvent(event string) error { func (e *Eventer) LaunchEvent(event string, data map[string]string) error {
_, ok := e.events[event] _, ok := e.events[event]
if !ok { if !ok {
return errors.New("Event " + event + " not found!") return errors.New("Event " + event + " not found!")
@ -47,7 +47,7 @@ func (e *Eventer) LaunchEvent(event string) error {
fmt.Println("Launching event " + event) fmt.Println("Launching event " + event)
for _, val := range e.events[event] { for _, val := range e.events[event] {
val() val(data)
} }
return nil return nil

View File

@ -56,7 +56,7 @@ func (l *Launcher) Initialize() {
fmt.Println("Initializing game launcher...") fmt.Println("Initializing game launcher...")
} }
func (l *Launcher) Launch(profile *datamodels.Profile, server string, password string, callback func()) { func (l *Launcher) Launch(server_profile *datamodels.Server, user_profile *datamodels.Profile, password string, additional_parameters []string, callback func()) {
// ToDo: only one instance of Urban Terror should be launched, so button // ToDo: only one instance of Urban Terror should be launched, so button
// should be disabled. // should be disabled.
fmt.Println("Launching Urban Terror...") fmt.Println("Launching Urban Terror...")
@ -65,23 +65,30 @@ func (l *Launcher) Launch(profile *datamodels.Profile, server string, password s
// Create launch string. // Create launch string.
var launch_bin string = "" var launch_bin string = ""
launch_bin, err := exec.LookPath(profile.Binary) launch_bin, err := exec.LookPath(user_profile.Binary)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
server_address := server_profile.Ip + ":" + server_profile.Port
var launch_params []string var launch_params []string
if len(server) > 0 { if len(server_address) > 0 {
launch_params = append(launch_params, "+connect", server) launch_params = append(launch_params, "+connect", server_address)
} }
if len(password) > 0 { if len(password) > 0 {
launch_params = append(launch_params, "+password", password) launch_params = append(launch_params, "+password", password)
} }
if len(profile.Additional_params) > 0 { if len(user_profile.Additional_params) > 0 {
additional_params := strings.Split(profile.Additional_params, " ") additional_params := strings.Split(user_profile.Additional_params, " ")
launch_params = append(launch_params, additional_params...) launch_params = append(launch_params, additional_params...)
} }
if profile.Second_x_session == "1" { if len(additional_parameters) > 0 {
for i := range additional_parameters {
launch_params = append(launch_params, additional_parameters[i])
}
}
if user_profile.Second_x_session == "1" {
fmt.Println(launch_params) fmt.Println(launch_params)
launch_params = append([]string{launch_bin}, launch_params...) launch_params = append([]string{launch_bin}, launch_params...)
display := l.findFreeDisplay() display := l.findFreeDisplay()

View File

@ -131,11 +131,11 @@ func (p *Pooler) UpdateOneServer(server_address string) {
}(server) }(server)
wait.Wait() wait.Wait()
p.PingOneServer(server_address) p.PingOneServer(server_address)
Eventer.LaunchEvent("flushServers") Eventer.LaunchEvent("flushServers", map[string]string{})
Eventer.LaunchEvent("loadAllServers") Eventer.LaunchEvent("loadAllServers", map[string]string{})
Eventer.LaunchEvent("loadFavoriteServers") Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
Eventer.LaunchEvent("serversUpdateCompleted") Eventer.LaunchEvent("serversUpdateCompleted", map[string]string{})
} }
func (p *Pooler) UpdateServers(servers_type string) { func (p *Pooler) UpdateServers(servers_type string) {
@ -153,11 +153,11 @@ func (p *Pooler) UpdateServers(servers_type string) {
} }
wait.Wait() wait.Wait()
p.PingServers(servers_type) p.PingServers(servers_type)
Eventer.LaunchEvent("flushServers") Eventer.LaunchEvent("flushServers", map[string]string{})
Eventer.LaunchEvent("loadAllServers") Eventer.LaunchEvent("loadAllServers", map[string]string{})
Eventer.LaunchEvent("loadFavoriteServers") Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
Eventer.LaunchEvent("serversUpdateCompleted") Eventer.LaunchEvent("serversUpdateCompleted", map[string]string{})
} }
// Updates information about specific server. // Updates information about specific server.

View File

@ -245,7 +245,7 @@ func (f *FavoriteDialog) saveFavorite() error {
ctx.Cache.Servers[key].Server.ExtendedConfig = f.server.ExtendedConfig ctx.Cache.Servers[key].Server.ExtendedConfig = f.server.ExtendedConfig
ctx.Cache.Servers[key].Server.PlayersInfo = f.server.PlayersInfo ctx.Cache.Servers[key].Server.PlayersInfo = f.server.PlayersInfo
ctx.Eventer.LaunchEvent("loadFavoriteServers") ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
f.window.Destroy() f.window.Destroy()
return nil return nil

View File

@ -11,7 +11,6 @@ package ui
import ( import (
// stdlib // stdlib
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -67,6 +66,8 @@ type MainWindow struct {
qc_server_address *gtk.Entry qc_server_address *gtk.Entry
// Quick connect: password // Quick connect: password
qc_password *gtk.Entry qc_password *gtk.Entry
// Quick connect: nickname
qc_nickname *gtk.Entry
// Tray icon. // Tray icon.
tray_icon *gtk.StatusIcon tray_icon *gtk.StatusIcon
// Tray menu. // Tray menu.
@ -219,7 +220,7 @@ func (m *MainWindow) deleteFromFavorites() {
d.Run() d.Run()
} }
ctx.Eventer.LaunchEvent("loadFavoriteServers") ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
} }
// Drop database data. // Drop database data.
@ -246,9 +247,9 @@ func (m *MainWindow) dropDatabasesData() {
ctx.Database.Db.MustExec("DELETE FROM settings") ctx.Database.Db.MustExec("DELETE FROM settings")
ctx.Database.Db.MustExec("DELETE FROM urt_profiles") ctx.Database.Db.MustExec("DELETE FROM urt_profiles")
ctx.Eventer.LaunchEvent("loadProfiles") ctx.Eventer.LaunchEvent("loadProfiles", map[string]string{})
ctx.Eventer.LaunchEvent("loadAllServers") ctx.Eventer.LaunchEvent("loadAllServers", map[string]string{})
ctx.Eventer.LaunchEvent("loadFavoriteServers") ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
} }
} }
@ -273,7 +274,7 @@ func (m *MainWindow) hideOfflineAllServers() {
} else { } else {
ctx.Cfg.Cfg["/serverslist/all_servers/hide_offline"] = "0" ctx.Cfg.Cfg["/serverslist/all_servers/hide_offline"] = "0"
} }
ctx.Eventer.LaunchEvent("loadAllServers") ctx.Eventer.LaunchEvent("loadAllServers", map[string]string{})
} }
// Executes when "Hide offline servers" checkbox changed it's state on // Executes when "Hide offline servers" checkbox changed it's state on
@ -285,138 +286,10 @@ func (m *MainWindow) hideOfflineFavoriteServers() {
} else { } else {
ctx.Cfg.Cfg["/serverslist/favorite/hide_offline"] = "0" ctx.Cfg.Cfg["/serverslist/favorite/hide_offline"] = "0"
} }
ctx.Eventer.LaunchEvent("loadFavoriteServers") ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
} }
func (m *MainWindow) launchGame() error { func (m *MainWindow) loadAllServers(data map[string]string) {
fmt.Println("Launching Urban Terror...")
// Getting server's name from list.
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
sel := m.all_servers.GetSelection()
model := m.all_servers.GetModel()
if strings.Contains(current_tab, "Favorites") {
sel = m.fav_servers.GetSelection()
model = m.fav_servers.GetModel()
}
iter := new(gtk.TreeIter)
_ = sel.GetSelected(iter)
// Getting server name.
var srv_name string
srv_name_gval := glib.ValueFromNative(srv_name)
if strings.Contains(current_tab, "Servers") {
model.GetValue(iter, m.column_pos["Servers"]["Name"], srv_name_gval)
} else if strings.Contains(current_tab, "Favorites") {
model.GetValue(iter, m.column_pos["Favorites"]["Name"], srv_name_gval)
}
server_name := srv_name_gval.GetString()
// Getting server address.
var srv_addr string
srv_address_gval := glib.ValueFromNative(srv_addr)
if strings.Contains(current_tab, "Servers") {
model.GetValue(iter, m.column_pos["Servers"]["IP"], srv_address_gval)
} else if strings.Contains(current_tab, "Favorites") {
model.GetValue(iter, m.column_pos["Favorites"]["IP"], srv_address_gval)
}
srv_address := srv_address_gval.GetString()
// Getting server's game version.
var srv_game_ver_raw string
srv_game_ver_gval := glib.ValueFromNative(srv_game_ver_raw)
if strings.Contains(current_tab, "Servers") {
model.GetValue(iter, m.column_pos["Servers"]["Version"], srv_game_ver_gval)
} else if strings.Contains(current_tab, "Favorites") {
model.GetValue(iter, m.column_pos["Favorites"]["Version"], srv_game_ver_gval)
}
srv_game_ver := srv_game_ver_gval.GetString()
// Check for proper server name. If length == 0: server is offline,
// we should show notification to user.
if len(server_name) == 0 {
var will_continue bool = false
mbox_string := "Selected server is offline.\n\nWould you still want to launch Urban Terror?\nIt will just launch a game, without connecting to\nany server."
m := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO, mbox_string)
m.Connect("response", func(resp *glib.CallbackContext) {
if resp.Args(0) == 4294967287 {
will_continue = false
} else {
will_continue = true
}
})
m.Response(func() {
m.Destroy()
})
m.Run()
if !will_continue {
return errors.New("User declined to connect to offline server")
}
}
// Getting selected profile's name.
profile_name := m.profiles.GetActiveText()
if strings.Contains(current_tab, "Servers") {
// Checking profile name length. If 0 - then stop executing :)
// This check only relevant to "Servers" tab, favorite servers
// have profiles defined (see next).
if len(profile_name) == 0 {
mbox_string := "Invalid game profile selected.\n\nPlease, select profile and retry."
m := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
m.Response(func() {
m.Destroy()
})
m.Run()
return errors.New("User didn't select valid profile.")
}
} else if strings.Contains(current_tab, "Favorites") {
// For favorite servers profile specified in favorite server
// information have higher priority, so we just override it :)
server := []datamodels.Server{}
// All favorites servers should contain IP and Port :)
ip := strings.Split(srv_address, ":")[0]
port := strings.Split(srv_address, ":")[1]
err := ctx.Database.Db.Select(&server, ctx.Database.Db.Rebind("SELECT * FROM servers WHERE ip=? AND port=?"), ip, port)
if err != nil {
fmt.Println(err.Error())
}
profile_name = server[0].ProfileToUse
}
// Getting profile data from database.
// ToDo: cache profiles data in runtime.
profile := []datamodels.Profile{}
err := ctx.Database.Db.Select(&profile, ctx.Database.Db.Rebind("SELECT * FROM urt_profiles WHERE name=?"), profile_name)
if err != nil {
fmt.Println(err.Error())
}
// Check if profile version is valid for selected game server.
if profile[0].Version != srv_game_ver {
mbox_string := "Invalid game profile selected.\n\nSelected profile have different game version than server.\nPlease, select valid profile and retry."
m := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
m.Response(func() {
m.Destroy()
})
m.Run()
return errors.New("User didn't select valid profile, mismatch with server's version.")
}
// Hey, we're ok here! :) Launch Urban Terror!
// Crear server name from "<markup></markup>" things.
srv_name_for_label := string([]byte(server_name)[8:len(server_name)-9])
fmt.Println(srv_name_for_label)
// Show great coloured label.
m.statusbar.Push(m.statusbar_context_id, "Launching Urban Terror...")
m.toolbar_label.SetMarkup("<markup><span foreground=\"red\" font_weight=\"bold\">Urban Terror is launched with profile </span><span foreground=\"blue\">" + profile[0].Name + "</span> <span foreground=\"red\" font_weight=\"bold\">and connected to </span><span foreground=\"orange\" font_weight=\"bold\">" + srv_name_for_label + "</span></markup>")
m.launch_button.SetSensitive(false)
// ToDo: handling server passwords.
ctx.Launcher.Launch(&profile[0], srv_address, "", m.unlockInterface)
return nil
}
func (m *MainWindow) loadAllServers() {
fmt.Println("Loading all servers...") fmt.Println("Loading all servers...")
// ToDo: do it without clearing. // ToDo: do it without clearing.
for _, server := range ctx.Cache.Servers { for _, server := range ctx.Cache.Servers {
@ -469,7 +342,7 @@ func (m *MainWindow) loadAllServers() {
} }
} }
func (m *MainWindow) loadFavoriteServers() { func (m *MainWindow) loadFavoriteServers(data map[string]string) {
fmt.Println("Loading favorite servers...") fmt.Println("Loading favorite servers...")
for _, server := range ctx.Cache.Servers { for _, server := range ctx.Cache.Servers {
iter := new(gtk.TreeIter) iter := new(gtk.TreeIter)
@ -534,7 +407,7 @@ func (m *MainWindow) loadFavoriteServers() {
} }
} }
func (m *MainWindow) loadProfiles() { func (m *MainWindow) loadProfiles(data map[string]string) {
fmt.Println("Loading profiles into combobox on MainWindow") fmt.Println("Loading profiles into combobox on MainWindow")
for i := 0; i < m.old_profiles_count; i++ { for i := 0; i < m.old_profiles_count; i++ {
// ComboBox indexes are shifting on element deletion, so we should // ComboBox indexes are shifting on element deletion, so we should
@ -542,22 +415,25 @@ func (m *MainWindow) loadProfiles() {
m.profiles.Remove(0) m.profiles.Remove(0)
} }
profiles := []datamodels.Profile{} for _, profile := range ctx.Cache.Profiles {
err := ctx.Database.Db.Select(&profiles, "SELECT * FROM urt_profiles") m.profiles.AppendText(profile.Profile.Name)
if err != nil {
fmt.Println(err.Error())
}
for p := range profiles {
m.profiles.AppendText(profiles[p].Name)
} }
m.old_profiles_count = len(profiles) m.old_profiles_count = len(ctx.Cache.Profiles)
fmt.Println("Added " + strconv.Itoa(m.old_profiles_count) + " profiles") fmt.Println("Added " + strconv.Itoa(m.old_profiles_count) + " profiles")
} }
func (m *MainWindow) serversUpdateCompleted() { func (m *MainWindow) serversUpdateCompleted(data map[string]string) {
m.statusbar.Push(m.statusbar_context_id, "Servers updated.") ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "Servers updated."})
m.toolbar_label.SetLabel("Servers updated.") }
func (m *MainWindow) setToolbarLabelText(data map[string]string) {
fmt.Println("Setting toolbar's label text...")
if strings.Contains(data["text"], "<markup>") {
m.toolbar_label.SetMarkup(data["text"])
} else {
m.toolbar_label.SetLabel(data["text"])
}
} }
func (m *MainWindow) showHide() { func (m *MainWindow) showHide() {
@ -687,8 +563,7 @@ func (m *MainWindow) showTrayMenu(cbx *glib.CallbackContext) {
// Unlocking interface after game shut down. // Unlocking interface after game shut down.
func (m *MainWindow) unlockInterface() { func (m *MainWindow) unlockInterface() {
m.launch_button.SetSensitive(true) m.launch_button.SetSensitive(true)
m.statusbar.Push(m.statusbar_context_id, "URTrator is ready.") ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "URTrator is ready."})
m.toolbar_label.SetLabel("URTrator is ready.")
} }
func (m *MainWindow) updateOneServer() { func (m *MainWindow) updateOneServer() {
@ -702,8 +577,7 @@ 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() {
m.statusbar.Push(m.statusbar_context_id, "Updating servers...") ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">Updating servers...</span></markup>"})
m.toolbar_label.SetMarkup("<markup><span foreground=\"red\" font_weight=\"bold\">Updating servers...</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

@ -139,21 +139,16 @@ func (m *MainWindow) Initialize() {
m.launch_button.SetImage(launch_button_image) m.launch_button.SetImage(launch_button_image)
profile_and_launch_hbox.PackStart(m.launch_button, false, true, 5) profile_and_launch_hbox.PackStart(m.launch_button, false, true, 5)
// Statusbar.
m.statusbar = gtk.NewStatusbar()
m.vbox.PackStart(m.statusbar, false, true, 0)
m.statusbar_context_id = m.statusbar.GetContextId("Status Bar")
m.statusbar.Push(m.statusbar_context_id, "URTrator is ready")
m.window.Add(m.vbox) m.window.Add(m.vbox)
m.window.ShowAll() m.window.ShowAll()
// Launch events. // Launch events.
ctx.Eventer.LaunchEvent("loadProfiles") ctx.Eventer.LaunchEvent("loadProfiles", map[string]string{})
ctx.Eventer.LaunchEvent("loadServersIntoCache") ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
ctx.Eventer.LaunchEvent("loadAllServers") ctx.Eventer.LaunchEvent("loadServersIntoCache", map[string]string{})
ctx.Eventer.LaunchEvent("loadFavoriteServers") ctx.Eventer.LaunchEvent("loadAllServers", map[string]string{})
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "URTrator is ready."})
gtk.Main() gtk.Main()
} }
@ -163,8 +158,9 @@ func (m *MainWindow) initializeEvents() {
fmt.Println("Initializing events...") fmt.Println("Initializing events...")
ctx.Eventer.AddEventHandler("loadAllServers", m.loadAllServers) ctx.Eventer.AddEventHandler("loadAllServers", m.loadAllServers)
ctx.Eventer.AddEventHandler("loadFavoriteServers", m.loadFavoriteServers) ctx.Eventer.AddEventHandler("loadFavoriteServers", m.loadFavoriteServers)
ctx.Eventer.AddEventHandler("loadProfiles", m.loadProfiles) ctx.Eventer.AddEventHandler("loadProfilesIntoMainWindow", m.loadProfiles)
ctx.Eventer.AddEventHandler("serversUpdateCompleted", m.serversUpdateCompleted) ctx.Eventer.AddEventHandler("serversUpdateCompleted", m.serversUpdateCompleted)
ctx.Eventer.AddEventHandler("setToolbarLabelText", m.setToolbarLabelText)
} }
// Main menu initialization. // Main menu initialization.
@ -269,6 +265,16 @@ func (m *MainWindow) initializeSidebar() {
m.qc_password.SetTooltipText(pass_tooltip) m.qc_password.SetTooltipText(pass_tooltip)
qc_vbox.PackStart(m.qc_password, false, true, 5) qc_vbox.PackStart(m.qc_password, false, true, 5)
// Nickname
nick_tooltip := "Nickname we will use"
nick_label := gtk.NewLabel("Nickname:")
nick_label.SetTooltipText(nick_tooltip)
qc_vbox.PackStart(nick_label, false, true, 5)
m.qc_nickname = gtk.NewEntry()
m.qc_nickname.SetTooltipText(nick_tooltip)
qc_vbox.PackStart(m.qc_nickname, false, true, 5)
m.hpane.Add2(sidebar_vbox) m.hpane.Add2(sidebar_vbox)
} }

192
ui/mainwindow_launch.go Normal file
View File

@ -0,0 +1,192 @@
package ui
import (
// stdlib
"errors"
"fmt"
"strings"
// Local
"github.com/pztrn/urtrator/datamodels"
// other
"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
)
func (m *MainWindow) launchGame() error {
fmt.Println("Launching Urban Terror...")
if len(m.qc_server_address.GetText()) != 0 {
m.launchWithQuickConnect()
} else {
m.launchAsUsual()
}
return nil
}
// Triggers if we clicked "Launch" button without any text in quick connect
// widget.
func (m *MainWindow) launchAsUsual() error {
fmt.Println("Connecting to selected server...")
var srv_address string = ""
// Getting server's name from list.
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
sel := m.all_servers.GetSelection()
model := m.all_servers.GetModel()
if strings.Contains(current_tab, "Favorites") {
sel = m.fav_servers.GetSelection()
model = m.fav_servers.GetModel()
}
iter := new(gtk.TreeIter)
_ = sel.GetSelected(iter)
// Getting server address.
var srv_addr string
srv_address_gval := glib.ValueFromNative(srv_addr)
if strings.Contains(current_tab, "Servers") {
model.GetValue(iter, m.column_pos["Servers"]["IP"], srv_address_gval)
} else if strings.Contains(current_tab, "Favorites") {
model.GetValue(iter, m.column_pos["Favorites"]["IP"], srv_address_gval)
}
srv_address = srv_address_gval.GetString()
server_profile := ctx.Cache.Servers[srv_address].Server
// Check for proper server name. If length == 0: server is offline,
// we should show notification to user.
if len(server_profile.Name) == 0 {
var will_continue bool = false
mbox_string := "Selected server is offline.\n\nWould you still want to launch Urban Terror?\nIt will just launch a game, without connecting to\nany server."
m := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO, mbox_string)
m.Connect("response", func(resp *glib.CallbackContext) {
if resp.Args(0) == 4294967287 {
will_continue = false
} else {
will_continue = true
}
})
m.Response(func() {
m.Destroy()
})
m.Run()
if !will_continue {
return errors.New("User declined to connect to offline server")
}
}
// Getting selected profile's name.
profile_name := m.profiles.GetActiveText()
user_profile := &datamodels.Profile{}
if strings.Contains(current_tab, "Servers") {
// Checking profile name length. If 0 - then stop executing :)
// This check only relevant to "Servers" tab, favorite servers
// have profiles defined (see next).
if len(profile_name) == 0 {
mbox_string := "Invalid game profile selected.\n\nPlease, select profile and retry."
m := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
m.Response(func() {
m.Destroy()
})
m.Run()
return errors.New("User didn't select valid profile.")
}
user_profile = ctx.Cache.Profiles[profile_name].Profile
} else if strings.Contains(current_tab, "Favorites") {
// For favorite servers profile specified in favorite server
// information have higher priority, so we just override it :)
user_profile = ctx.Cache.Profiles[server_profile.ProfileToUse].Profile
}
m.launchActually(server_profile, user_profile, "", "")
return nil
}
// Triggers when Launch button was clicked with some text in quick connect
// widget.
func (m *MainWindow) launchWithQuickConnect() error {
fmt.Println("Launching game with data from quick connect...")
srv_address := m.qc_server_address.GetText()
srv_password := m.qc_password.GetText()
srv_nickname := m.qc_nickname.GetText()
current_profile_name := m.profiles.GetActiveText()
// As we're launching without any profile defined - we should
// check server version and globally selected profile.
// Checking if we have server defined in cache.
var ip string = ""
var port string = ""
if strings.Contains(srv_address, ":") {
ip = strings.Split(srv_address, ":")[0]
port = strings.Split(srv_address, ":")[1]
} else {
ip = strings.Split(srv_address, ":")[0]
port = "27960"
}
key := ip + ":" + port
_, ok := ctx.Cache.Servers[key]
if !ok {
ctx.Cache.CreateServer(key)
fmt.Println("Server not found in cache, requesting information...")
ctx.Requester.UpdateOneServer(key)
}
server_profile := ctx.Cache.Servers[key]
user_profile := ctx.Cache.Profiles[current_profile_name]
m.launchActually(server_profile.Server, user_profile.Profile, srv_password, srv_nickname)
return nil
}
func (m *MainWindow) launchActually(server_profile *datamodels.Server, user_profile *datamodels.Profile, password string, nickname_to_use string) error {
if server_profile.Name == "" {
var will_continue bool = false
mbox_string := "Selected server is offline.\n\nWould you still want to launch Urban Terror?\nIt will just launch a game, without connecting to\nany server."
m := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO, mbox_string)
m.Connect("response", func(resp *glib.CallbackContext) {
if resp.Args(0) == 4294967287 {
will_continue = false
} else {
will_continue = true
}
})
m.Response(func() {
m.Destroy()
})
m.Run()
if !will_continue {
return errors.New("User declined to connect to offline server")
}
}
// Check if server is applicable for selected profile.
if server_profile.Version != user_profile.Version {
mbox_string := "Invalid game profile selected.\n\nSelected profile have different game version than server.\nPlease, select valid profile and retry."
m := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
m.Response(func() {
m.Destroy()
})
m.Run()
return errors.New("User didn't select valid profile, mismatch with server's version.")
}
server_password := password
if len(server_password) == 0 {
server_password = server_profile.Password
}
// Hey, we're ok here! :) Launch Urban Terror!
// Crear server name from "<markup></markup>" things.
srv_name_for_label := string([]byte(server_profile.Name)[8:len(server_profile.Name)-9])
fmt.Println(srv_name_for_label)
// Show great coloured label.
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">Urban Terror is launched with profile </span><span foreground=\"blue\">" + user_profile.Name + "</span> <span foreground=\"red\" font_weight=\"bold\">and connected to </span><span foreground=\"orange\" font_weight=\"bold\">" + srv_name_for_label + "</span></markup>"})
m.launch_button.SetSensitive(false)
// ToDo: handling server passwords.
ctx.Launcher.Launch(server_profile, user_profile, server_password, []string{"+name", nickname_to_use}, m.unlockInterface)
return nil
}

View File

@ -48,8 +48,10 @@ func (o *OptionsDialog) addProfile() {
fmt.Println("Adding profile...") fmt.Println("Adding profile...")
op := OptionsProfile{} op := OptionsProfile{}
op.Initialize(false, o.loadProfiles) op.Initialize(false)
ctx.Eventer.LaunchEvent("loadProfiles") 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() { func (o *OptionsDialog) closeOptionsDialogByCancel() {
@ -71,8 +73,6 @@ func (o *OptionsDialog) closeOptionsDialogWithSaving() {
}) })
m.Run() m.Run()
ctx.Eventer.LaunchEvent("loadProfiles")
o.window.Destroy() o.window.Destroy()
} }
@ -92,8 +92,10 @@ func (o *OptionsDialog) deleteProfile() {
profile := datamodels.Profile{} profile := datamodels.Profile{}
profile.Name = profile_name profile.Name = profile_name
ctx.Database.Db.NamedExec("DELETE FROM urt_profiles WHERE name=:name", &profile) ctx.Eventer.LaunchEvent("deleteProfile", map[string]string{"profile_name": profile_name})
ctx.Eventer.LaunchEvent("loadProfiles") ctx.Eventer.LaunchEvent("flushProfiles", map[string]string{})
ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
} }
} }
@ -110,8 +112,10 @@ func (o *OptionsDialog) editProfile() {
if len(profile_name) > 0 { if len(profile_name) > 0 {
op := OptionsProfile{} op := OptionsProfile{}
op.InitializeUpdate(profile_name, o.loadProfiles) op.InitializeUpdate(profile_name)
ctx.Eventer.LaunchEvent("loadProfiles") ctx.Eventer.LaunchEvent("flushProfiles", map[string]string{})
ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
} }
} }
@ -169,6 +173,8 @@ func (o *OptionsDialog) initializeTabs() {
o.vbox.PackStart(o.tab_widget, true, true, 5) o.vbox.PackStart(o.tab_widget, true, true, 5)
o.vbox.PackStart(buttons_hbox, false, true, 5) o.vbox.PackStart(buttons_hbox, false, true, 5)
ctx.Eventer.AddEventHandler("loadProfilesIntoOptionsWindow", o.loadProfiles)
} }
func (o *OptionsDialog) initializeUrtTab() { func (o *OptionsDialog) initializeUrtTab() {
@ -213,26 +219,18 @@ func (o *OptionsDialog) initializeUrtTab() {
o.tab_widget.AppendPage(urt_hbox, gtk.NewLabel("Urban Terror")) o.tab_widget.AppendPage(urt_hbox, gtk.NewLabel("Urban Terror"))
// Load Profiles. // Load Profiles.
o.loadProfiles() ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
} }
func (o *OptionsDialog) loadProfiles() { func (o *OptionsDialog) loadProfiles(data map[string]string) {
fmt.Println("Loading profiles...") fmt.Println("Loading profiles...")
o.profiles_list_store.Clear() o.profiles_list_store.Clear()
// Get profiles from database.
profiles := []datamodels.Profile{}
err := ctx.Database.Db.Select(&profiles, "SELECT * FROM urt_profiles")
if err != nil {
fmt.Println(err.Error())
}
for p := range profiles { for _, p := range ctx.Cache.Profiles {
var iter gtk.TreeIter var iter gtk.TreeIter
o.profiles_list_store.Append(&iter) o.profiles_list_store.Append(&iter)
o.profiles_list_store.Set(&iter, 0, profiles[p].Name) o.profiles_list_store.Set(&iter, 0, p.Profile.Name)
o.profiles_list_store.Set(&iter, 1, profiles[p].Version) o.profiles_list_store.Set(&iter, 1, p.Profile.Version)
//state, _ := strconv.ParseBool(profiles[p].Second_x_session)
//o.profiles_list_store.Set(&iter, 2, state)
} }
} }
@ -267,5 +265,8 @@ func (o *OptionsDialog) ShowOptionsDialog() {
o.fill() o.fill()
o.window.Add(o.vbox) o.window.Add(o.vbox)
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
o.window.ShowAll() o.window.ShowAll()
} }

View File

@ -47,10 +47,6 @@ type OptionsProfile struct {
// This is profile update? // This is profile update?
update bool update bool
// Callbacks.
// This will be triggered after we change profile.
loadProfiles func()
// Others. // Others.
// Old profile, needed for proper update. // Old profile, needed for proper update.
old_profile *datamodels.Profile old_profile *datamodels.Profile
@ -105,13 +101,11 @@ func (op *OptionsProfile) closeByCancel() {
func (op *OptionsProfile) closeWithDiscard() { func (op *OptionsProfile) closeWithDiscard() {
} }
func (op *OptionsProfile) Initialize(update bool, lp func()) { func (op *OptionsProfile) Initialize(update bool) {
if update { if update {
op.update = true op.update = true
} }
op.loadProfiles = lp
op.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL) op.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
if update { if update {
op.window.SetTitle("URTrator - Update Urban Terror profile") op.window.SetTitle("URTrator - Update Urban Terror profile")
@ -233,9 +227,9 @@ func (op *OptionsProfile) Initialize(update bool, lp func()) {
op.window.ShowAll() op.window.ShowAll()
} }
func (op *OptionsProfile) InitializeUpdate(profile_name string, lp func()) { func (op *OptionsProfile) InitializeUpdate(profile_name string) {
fmt.Println("Updating profile '" + profile_name + "'") fmt.Println("Updating profile '" + profile_name + "'")
op.Initialize(true, lp) op.Initialize(true)
// Get profile data. // Get profile data.
profile := []datamodels.Profile{} profile := []datamodels.Profile{}
@ -284,7 +278,7 @@ func (op *OptionsProfile) saveProfile() {
m.Run() m.Run()
} }
// ...and must be executable! :) // ...and must be executable! :)
filestat, err := os.Stat(op.binary_path.GetText()) _, err := os.Stat(op.binary_path.GetText())
if err != nil { if err != nil {
mbox_string := "Invalid path to binary!\n\nError was:\n" + err.Error() + "\n\nCheck binary path and try again." mbox_string := "Invalid path to binary!\n\nError was:\n" + err.Error() + "\n\nCheck binary path and try again."
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string) m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
@ -294,37 +288,11 @@ func (op *OptionsProfile) saveProfile() {
m.Run() m.Run()
} else { } else {
// ToDo: executable flag checking. // ToDo: executable flag checking.
fmt.Println(filestat.Mode()) //fmt.Println(filestat.Mode())
profile_name := op.profile_name.GetText()
// If we here - we can try to save game profile :). _, ok := ctx.Cache.Profiles[profile_name]
profile := datamodels.Profile{ if ok && !op.update {
Name: op.profile_name.GetText(),
Version: op.urt_version_combo.GetActiveText(),
Binary: op.binary_path.GetText(),
Additional_params: op.additional_parameters.GetText(),
}
if op.another_x_session.GetActive() {
profile.Second_x_session = "1"
} else {
profile.Second_x_session = "0"
}
// Check if we already have profile with such name.
profiles := []datamodels.Profile{}
err1 := ctx.Database.Db.Select(&profiles, "SELECT * FROM urt_profiles")
if err1 != nil {
fmt.Println(err1.Error())
}
var found bool = false
for p := range profiles {
if profiles[p].Name == profile.Name {
found = true
}
}
if found && profile.Version == op.old_profile.Version && profile.Binary == op.old_profile.Binary && profile.Name == op.old_profile.Name && profile.Second_x_session == op.old_profile.Second_x_session {
mbox_string := "Game profile with same name already exist.\nRename profile for saving." mbox_string := "Game profile with same name already exist.\nRename profile for saving."
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string) m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
m.Response(func() { m.Response(func() {
@ -332,13 +300,20 @@ func (op *OptionsProfile) saveProfile() {
}) })
m.Run() m.Run()
} else { } else {
if op.update { ctx.Cache.CreateProfile(profile_name)
ctx.Database.Db.NamedExec("UPDATE urt_profiles SET name=:name, version=:version, binary=:binary, second_x_session=:second_x_session, additional_parameters=:additional_parameters WHERE name='" + op.old_profile.Name + "'", &profile) ctx.Cache.Profiles[profile_name].Profile.Name = profile_name
ctx.Cache.Profiles[profile_name].Profile.Version = op.urt_version_combo.GetActiveText()
ctx.Cache.Profiles[profile_name].Profile.Binary = op.binary_path.GetText()
ctx.Cache.Profiles[profile_name].Profile.Additional_params = op.additional_parameters.GetText()
if op.another_x_session.GetActive() {
ctx.Cache.Profiles[profile_name].Profile.Second_x_session = "1"
} else { } else {
ctx.Database.Db.NamedExec("INSERT INTO urt_profiles (name, version, binary, second_x_session, additional_parameters) VALUES (:name, :version, :binary, :second_x_session, :additional_parameters)", &profile) ctx.Cache.Profiles[profile_name].Profile.Second_x_session = "0"
} }
} }
} }
op.loadProfiles() ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
op.window.Destroy() op.window.Destroy()
} }