Updated to latest GTK2 bindings API and moved to Gitlab.
This commit is contained in:
parent
070aa50762
commit
127e1b8ab9
50
cache/cache_object.go
vendored
50
cache/cache_object.go
vendored
@ -10,41 +10,41 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
"sync"
|
||||
// stdlib
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/cachemodels"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/cachemodels"
|
||||
)
|
||||
|
||||
type Cache struct {
|
||||
// Profiles cache.
|
||||
Profiles map[string]*cachemodels.Profile
|
||||
// Profiles cache mutex.
|
||||
ProfilesMutex sync.Mutex
|
||||
// Servers cache.
|
||||
Servers map[string]*cachemodels.Server
|
||||
// Servers cache mutex.
|
||||
ServersMutex sync.Mutex
|
||||
// Profiles cache.
|
||||
Profiles map[string]*cachemodels.Profile
|
||||
// Profiles cache mutex.
|
||||
ProfilesMutex sync.Mutex
|
||||
// Servers cache.
|
||||
Servers map[string]*cachemodels.Server
|
||||
// Servers cache mutex.
|
||||
ServersMutex sync.Mutex
|
||||
}
|
||||
|
||||
func (c *Cache) Initialize() {
|
||||
fmt.Println("Initializing cache...")
|
||||
c.initializeStorages()
|
||||
c.LoadServers(map[string]string{})
|
||||
fmt.Println("Initializing cache...")
|
||||
c.initializeStorages()
|
||||
c.LoadServers(map[string]string{})
|
||||
|
||||
Eventer.AddEventHandler("deleteProfile", c.deleteProfile)
|
||||
Eventer.AddEventHandler("flushProfiles", c.FlushProfiles)
|
||||
Eventer.AddEventHandler("loadProfiles", c.LoadProfiles)
|
||||
Eventer.AddEventHandler("deleteProfile", c.deleteProfile)
|
||||
Eventer.AddEventHandler("flushProfiles", c.FlushProfiles)
|
||||
Eventer.AddEventHandler("loadProfiles", c.LoadProfiles)
|
||||
|
||||
Eventer.AddEventHandler("flushServers", c.FlushServers)
|
||||
Eventer.AddEventHandler("loadServersIntoCache", c.LoadServers)
|
||||
Eventer.AddEventHandler("flushServers", c.FlushServers)
|
||||
Eventer.AddEventHandler("loadServersIntoCache", c.LoadServers)
|
||||
}
|
||||
|
||||
func (c *Cache) initializeStorages() {
|
||||
// Profiles cache.
|
||||
c.Profiles = make(map[string]*cachemodels.Profile)
|
||||
// Servers cache.
|
||||
c.Servers = make(map[string]*cachemodels.Server)
|
||||
// Profiles cache.
|
||||
c.Profiles = make(map[string]*cachemodels.Profile)
|
||||
// Servers cache.
|
||||
c.Servers = make(map[string]*cachemodels.Server)
|
||||
}
|
||||
|
154
cache/cache_profiles.go
vendored
154
cache/cache_profiles.go
vendored
@ -10,105 +10,105 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
"strconv"
|
||||
// stdlib
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/cachemodels"
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/cachemodels"
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
)
|
||||
|
||||
func (c *Cache) CreateProfile(name string) {
|
||||
fmt.Println("Creating profile " + name)
|
||||
_, ok := c.Profiles[name]
|
||||
fmt.Println("Creating profile " + name)
|
||||
_, ok := c.Profiles[name]
|
||||
|
||||
if !ok {
|
||||
c.ProfilesMutex.Lock()
|
||||
c.Profiles[name] = &cachemodels.Profile{}
|
||||
c.Profiles[name].Profile = &datamodels.Profile{}
|
||||
c.ProfilesMutex.Unlock()
|
||||
}
|
||||
if !ok {
|
||||
c.ProfilesMutex.Lock()
|
||||
c.Profiles[name] = &cachemodels.Profile{}
|
||||
c.Profiles[name].Profile = &datamodels.Profile{}
|
||||
c.ProfilesMutex.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) deleteProfile(data map[string]string) {
|
||||
fmt.Println("Deleting profile " + data["profile_name"])
|
||||
fmt.Println("Deleting profile " + data["profile_name"])
|
||||
|
||||
c.ProfilesMutex.Lock()
|
||||
_, ok := c.Profiles[data["profile_name"]]
|
||||
c.ProfilesMutex.Unlock()
|
||||
if ok {
|
||||
c.ProfilesMutex.Lock()
|
||||
delete(c.Profiles, data["profile_name"])
|
||||
c.ProfilesMutex.Unlock()
|
||||
}
|
||||
c.ProfilesMutex.Lock()
|
||||
_, ok := c.Profiles[data["profile_name"]]
|
||||
c.ProfilesMutex.Unlock()
|
||||
if ok {
|
||||
c.ProfilesMutex.Lock()
|
||||
delete(c.Profiles, data["profile_name"])
|
||||
c.ProfilesMutex.Unlock()
|
||||
}
|
||||
|
||||
c.ProfilesMutex.Lock()
|
||||
_, ok1 := c.Profiles[data["profile_name"]]
|
||||
c.ProfilesMutex.Unlock()
|
||||
if !ok1 {
|
||||
Database.Db.MustExec(Database.Db.Rebind("DELETE FROM urt_profiles WHERE name=?"), data["profile_name"])
|
||||
fmt.Println("Profile deleted")
|
||||
} else {
|
||||
fmt.Println("Something goes wrong! Profile is still here!")
|
||||
}
|
||||
c.ProfilesMutex.Lock()
|
||||
_, ok1 := c.Profiles[data["profile_name"]]
|
||||
c.ProfilesMutex.Unlock()
|
||||
if !ok1 {
|
||||
Database.Db.MustExec(Database.Db.Rebind("DELETE FROM urt_profiles WHERE name=?"), data["profile_name"])
|
||||
fmt.Println("Profile deleted")
|
||||
} else {
|
||||
fmt.Println("Something goes wrong! Profile is still here!")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) FlushProfiles(data map[string]string) {
|
||||
fmt.Println("Flushing profiles to database...")
|
||||
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())
|
||||
}
|
||||
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] = c.Profiles[raw_profiles[i].Name].Profile
|
||||
}
|
||||
cached_profiles := make(map[string]*datamodels.Profile)
|
||||
for i := range raw_profiles {
|
||||
cached_profiles[raw_profiles[i].Name] = c.Profiles[raw_profiles[i].Name].Profile
|
||||
}
|
||||
|
||||
new_profiles := make(map[string]*datamodels.Profile)
|
||||
new_profiles := make(map[string]*datamodels.Profile)
|
||||
|
||||
c.ProfilesMutex.Lock()
|
||||
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] = profile.Profile
|
||||
}
|
||||
}
|
||||
c.ProfilesMutex.Unlock()
|
||||
c.ProfilesMutex.Lock()
|
||||
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] = profile.Profile
|
||||
}
|
||||
}
|
||||
c.ProfilesMutex.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, profile_path) VALUES (:name, :version, :binary, :second_x_session, :additional_parameters, :profile_path)", &profile)
|
||||
}
|
||||
fmt.Println("Updating existing profiles...")
|
||||
for _, profile := range cached_profiles {
|
||||
fmt.Println(fmt.Sprintf("%+v", profile))
|
||||
tx.NamedExec("UPDATE urt_profiles SET name=:name, version=:version, binary=:binary, second_x_session=:second_x_session, additional_parameters=:additional_parameters, profile_path=:profile_path WHERE name=:name", &profile)
|
||||
}
|
||||
tx.Commit()
|
||||
fmt.Println("Done")
|
||||
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, profile_path) VALUES (:name, :version, :binary, :second_x_session, :additional_parameters, :profile_path)", &profile)
|
||||
}
|
||||
fmt.Println("Updating existing profiles...")
|
||||
for _, profile := range cached_profiles {
|
||||
fmt.Println(fmt.Sprintf("%+v", profile))
|
||||
tx.NamedExec("UPDATE urt_profiles SET name=:name, version=:version, binary=:binary, second_x_session=:second_x_session, additional_parameters=:additional_parameters, profile_path=:profile_path WHERE name=:name", &profile)
|
||||
}
|
||||
tx.Commit()
|
||||
fmt.Println("Done")
|
||||
}
|
||||
|
||||
func (c *Cache) LoadProfiles(data map[string]string) {
|
||||
fmt.Println("Loading profiles to cache...")
|
||||
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())
|
||||
}
|
||||
raw_profiles := []datamodels.Profile{}
|
||||
err := Database.Db.Select(&raw_profiles, "SELECT * FROM urt_profiles")
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
|
||||
c.ProfilesMutex.Lock()
|
||||
for _, profile := range raw_profiles {
|
||||
c.Profiles[profile.Name] = &cachemodels.Profile{}
|
||||
c.Profiles[profile.Name].Profile = &profile
|
||||
}
|
||||
c.ProfilesMutex.Unlock()
|
||||
c.ProfilesMutex.Lock()
|
||||
for _, profile := range raw_profiles {
|
||||
c.Profiles[profile.Name] = &cachemodels.Profile{}
|
||||
c.Profiles[profile.Name].Profile = &profile
|
||||
}
|
||||
c.ProfilesMutex.Unlock()
|
||||
|
||||
fmt.Println("Load completed. Loaded " + strconv.Itoa(len(c.Profiles)) + " profiles.")
|
||||
fmt.Println("Load completed. Loaded " + strconv.Itoa(len(c.Profiles)) + " profiles.")
|
||||
}
|
||||
|
228
cache/cache_servers.go
vendored
228
cache/cache_servers.go
vendored
@ -10,135 +10,135 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
// stdlib
|
||||
"fmt"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/cachemodels"
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/cachemodels"
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
)
|
||||
|
||||
func (c *Cache) CreateServer(addr string) {
|
||||
_, ok := c.Servers[addr]
|
||||
if !ok {
|
||||
c.ServersMutex.Lock()
|
||||
c.Servers[addr] = &cachemodels.Server{}
|
||||
c.Servers[addr].Server = &datamodels.Server{}
|
||||
c.ServersMutex.Unlock()
|
||||
} else {
|
||||
fmt.Println("Server " + addr + " already exist.")
|
||||
}
|
||||
_, ok := c.Servers[addr]
|
||||
if !ok {
|
||||
c.ServersMutex.Lock()
|
||||
c.Servers[addr] = &cachemodels.Server{}
|
||||
c.Servers[addr].Server = &datamodels.Server{}
|
||||
c.ServersMutex.Unlock()
|
||||
} 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")
|
||||
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]
|
||||
}
|
||||
// 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)
|
||||
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].Bots = s.Server.Bots
|
||||
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
|
||||
new_servers[mapping_item_name].Favorite = s.Server.Favorite
|
||||
new_servers[mapping_item_name].ProfileToUse = s.Server.ProfileToUse
|
||||
new_servers[mapping_item_name].Password = s.Server.Password
|
||||
} 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].Bots = s.Server.Bots
|
||||
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
|
||||
cached_servers[mapping_item_name].Favorite = s.Server.Favorite
|
||||
cached_servers[mapping_item_name].ProfileToUse = s.Server.ProfileToUse
|
||||
cached_servers[mapping_item_name].Password = s.Server.Password
|
||||
}
|
||||
}
|
||||
// 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].Bots = s.Server.Bots
|
||||
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
|
||||
new_servers[mapping_item_name].Favorite = s.Server.Favorite
|
||||
new_servers[mapping_item_name].ProfileToUse = s.Server.ProfileToUse
|
||||
new_servers[mapping_item_name].Password = s.Server.Password
|
||||
} 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].Bots = s.Server.Bots
|
||||
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
|
||||
cached_servers[mapping_item_name].Favorite = s.Server.Favorite
|
||||
cached_servers[mapping_item_name].ProfileToUse = s.Server.ProfileToUse
|
||||
cached_servers[mapping_item_name].Password = s.Server.Password
|
||||
}
|
||||
}
|
||||
|
||||
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, favorite, profile_to_use, bots) VALUES (:ip, :port, :name, :ping, :players, :maxplayers, :gamemode, :map, :version, :extended_config, :players_info, :is_private, :favorite, :profile_to_use, :bots)", 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, favorite=:favorite, password=:password, players_info=:players_info, is_private=:is_private, profile_to_use=:profile_to_use, bots=:bots WHERE ip=:ip AND port=:port", &srv)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}
|
||||
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, favorite, profile_to_use, bots) VALUES (:ip, :port, :name, :ping, :players, :maxplayers, :gamemode, :map, :version, :extended_config, :players_info, :is_private, :favorite, :profile_to_use, :bots)", 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, favorite=:favorite, password=:password, players_info=:players_info, is_private=:is_private, profile_to_use=:profile_to_use, bots=:bots WHERE ip=:ip AND port=:port", &srv)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
fmt.Println("Done")
|
||||
tx.Commit()
|
||||
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())
|
||||
}
|
||||
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.Bots = server.Bots
|
||||
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.")
|
||||
// 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.Bots = server.Bots
|
||||
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.")
|
||||
}
|
||||
|
18
cache/exported.go
vendored
18
cache/exported.go
vendored
@ -10,19 +10,19 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
// local
|
||||
event "github.com/pztrn/urtrator/eventer"
|
||||
"github.com/pztrn/urtrator/database"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/database"
|
||||
event "gitlab.com/pztrn/urtrator/eventer"
|
||||
)
|
||||
|
||||
var (
|
||||
Database *database.Database
|
||||
Eventer *event.Eventer
|
||||
Database *database.Database
|
||||
Eventer *event.Eventer
|
||||
)
|
||||
|
||||
func New(d *database.Database, e *event.Eventer) *Cache {
|
||||
Database = d
|
||||
Eventer = e
|
||||
c := Cache{}
|
||||
return &c
|
||||
Database = d
|
||||
Eventer = e
|
||||
c := Cache{}
|
||||
return &c
|
||||
}
|
||||
|
@ -10,10 +10,10 @@
|
||||
package cachemodels
|
||||
|
||||
import (
|
||||
// local
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
)
|
||||
|
||||
type Profile struct {
|
||||
Profile *datamodels.Profile
|
||||
Profile *datamodels.Profile
|
||||
}
|
||||
|
@ -10,20 +10,20 @@
|
||||
package cachemodels
|
||||
|
||||
import (
|
||||
// local
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Server *datamodels.Server
|
||||
AllServersIter *gtk.TreeIter
|
||||
AllServersIterSet bool
|
||||
AllServersIterInList bool
|
||||
Server *datamodels.Server
|
||||
AllServersIter *gtk.TreeIter
|
||||
AllServersIterSet bool
|
||||
AllServersIterInList bool
|
||||
|
||||
FavServersIter *gtk.TreeIter
|
||||
FavServersIterSet bool
|
||||
FavServersIterInList bool
|
||||
FavServersIter *gtk.TreeIter
|
||||
FavServersIterSet bool
|
||||
FavServersIterInList bool
|
||||
}
|
||||
|
@ -9,20 +9,20 @@
|
||||
// ToDo: put full text of license here.
|
||||
package clipboardwatcher
|
||||
|
||||
import(
|
||||
// local
|
||||
"github.com/pztrn/urtrator/cache"
|
||||
"github.com/pztrn/urtrator/eventer"
|
||||
import (
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/cache"
|
||||
"gitlab.com/pztrn/urtrator/eventer"
|
||||
)
|
||||
|
||||
var (
|
||||
Cache *cache.Cache
|
||||
Eventer *eventer.Eventer
|
||||
Cache *cache.Cache
|
||||
Eventer *eventer.Eventer
|
||||
)
|
||||
|
||||
func New(c *cache.Cache, e *eventer.Eventer) *ClipboardWatcher {
|
||||
Cache = c
|
||||
Eventer = e
|
||||
cw := ClipboardWatcher{}
|
||||
return &cw
|
||||
Cache = c
|
||||
Eventer = e
|
||||
cw := ClipboardWatcher{}
|
||||
return &cw
|
||||
}
|
||||
|
@ -10,125 +10,125 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"errors"
|
||||
"fmt"
|
||||
// stdlib
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/cache"
|
||||
"github.com/pztrn/urtrator/clipboardwatcher"
|
||||
"github.com/pztrn/urtrator/colorizer"
|
||||
"github.com/pztrn/urtrator/configuration"
|
||||
"github.com/pztrn/urtrator/database"
|
||||
"github.com/pztrn/urtrator/eventer"
|
||||
"github.com/pztrn/urtrator/launcher"
|
||||
"github.com/pztrn/urtrator/requester"
|
||||
"github.com/pztrn/urtrator/timer"
|
||||
"github.com/pztrn/urtrator/translator"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/cache"
|
||||
"gitlab.com/pztrn/urtrator/clipboardwatcher"
|
||||
"gitlab.com/pztrn/urtrator/colorizer"
|
||||
"gitlab.com/pztrn/urtrator/configuration"
|
||||
"gitlab.com/pztrn/urtrator/database"
|
||||
"gitlab.com/pztrn/urtrator/eventer"
|
||||
"gitlab.com/pztrn/urtrator/launcher"
|
||||
"gitlab.com/pztrn/urtrator/requester"
|
||||
"gitlab.com/pztrn/urtrator/timer"
|
||||
"gitlab.com/pztrn/urtrator/translator"
|
||||
|
||||
// Github
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
// Github
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
// Caching.
|
||||
Cache *cache.Cache
|
||||
// Clipboard watcher.
|
||||
Clipboard *clipboardwatcher.ClipboardWatcher
|
||||
// Colors parser and prettifier.
|
||||
Colorizer *colorizer.Colorizer
|
||||
// Configuration.
|
||||
Cfg *configuration.Config
|
||||
// Database.
|
||||
Database *database.Database
|
||||
// Eventer.
|
||||
Eventer *eventer.Eventer
|
||||
// Game launcher.
|
||||
Launcher *launcher.Launcher
|
||||
// Requester, which requests server's information.
|
||||
Requester *requester.Requester
|
||||
// Timer.
|
||||
Timer *timer.Timer
|
||||
// Translator.
|
||||
Translator *translator.Translator
|
||||
// Caching.
|
||||
Cache *cache.Cache
|
||||
// Clipboard watcher.
|
||||
Clipboard *clipboardwatcher.ClipboardWatcher
|
||||
// Colors parser and prettifier.
|
||||
Colorizer *colorizer.Colorizer
|
||||
// Configuration.
|
||||
Cfg *configuration.Config
|
||||
// Database.
|
||||
Database *database.Database
|
||||
// Eventer.
|
||||
Eventer *eventer.Eventer
|
||||
// Game launcher.
|
||||
Launcher *launcher.Launcher
|
||||
// Requester, which requests server's information.
|
||||
Requester *requester.Requester
|
||||
// Timer.
|
||||
Timer *timer.Timer
|
||||
// Translator.
|
||||
Translator *translator.Translator
|
||||
}
|
||||
|
||||
func (ctx *Context) Close() error {
|
||||
fmt.Println("Closing URTrator...")
|
||||
fmt.Println("Closing URTrator...")
|
||||
|
||||
launched := ctx.Launcher.CheckForLaunchedUrbanTerror()
|
||||
if launched != nil {
|
||||
return errors.New("Urban Terror is launched!")
|
||||
}
|
||||
ctx.Cache.FlushProfiles(map[string]string{})
|
||||
ctx.Cache.FlushServers(map[string]string{})
|
||||
ctx.Database.Close()
|
||||
launched := ctx.Launcher.CheckForLaunchedUrbanTerror()
|
||||
if launched != nil {
|
||||
return errors.New("Urban Terror is launched!")
|
||||
}
|
||||
ctx.Cache.FlushProfiles(map[string]string{})
|
||||
ctx.Cache.FlushServers(map[string]string{})
|
||||
ctx.Database.Close()
|
||||
|
||||
// At last, close main window.
|
||||
gtk.MainQuit()
|
||||
return nil
|
||||
// At last, close main window.
|
||||
gtk.MainQuit()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeCache() {
|
||||
ctx.Cache = cache.New(ctx.Database, ctx.Eventer)
|
||||
ctx.Cache.Initialize()
|
||||
ctx.Cache = cache.New(ctx.Database, ctx.Eventer)
|
||||
ctx.Cache.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) InitializeClipboardWatcher() {
|
||||
ctx.Clipboard = clipboardwatcher.New(ctx.Cache, ctx.Eventer)
|
||||
ctx.Clipboard.Initialize()
|
||||
ctx.Clipboard = clipboardwatcher.New(ctx.Cache, ctx.Eventer)
|
||||
ctx.Clipboard.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeColorizer() {
|
||||
ctx.Colorizer = colorizer.New()
|
||||
ctx.Colorizer.Initialize()
|
||||
ctx.Colorizer = colorizer.New()
|
||||
ctx.Colorizer.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeConfig() {
|
||||
ctx.Cfg = configuration.New()
|
||||
ctx.Cfg.Initialize()
|
||||
ctx.Cfg = configuration.New()
|
||||
ctx.Cfg.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeDatabase() {
|
||||
ctx.Database = database.New(ctx.Cfg)
|
||||
ctx.Database.Initialize(ctx.Cfg)
|
||||
ctx.Database.Migrate()
|
||||
ctx.Database = database.New(ctx.Cfg)
|
||||
ctx.Database.Initialize(ctx.Cfg)
|
||||
ctx.Database.Migrate()
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeEventer() {
|
||||
ctx.Eventer = eventer.New()
|
||||
ctx.Eventer.Initialize()
|
||||
ctx.Eventer = eventer.New()
|
||||
ctx.Eventer.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeLauncher() {
|
||||
ctx.Launcher = launcher.New()
|
||||
ctx.Launcher.Initialize()
|
||||
ctx.Launcher = launcher.New()
|
||||
ctx.Launcher.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeRequester() {
|
||||
ctx.Requester = requester.New(ctx.Cache, ctx.Eventer, ctx.Cfg, ctx.Timer)
|
||||
ctx.Requester.Initialize()
|
||||
ctx.Requester = requester.New(ctx.Cache, ctx.Eventer, ctx.Cfg, ctx.Timer)
|
||||
ctx.Requester.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeTimer() {
|
||||
ctx.Timer = timer.New(ctx.Eventer, ctx.Cfg)
|
||||
ctx.Timer.Initialize()
|
||||
ctx.Timer = timer.New(ctx.Eventer, ctx.Cfg)
|
||||
ctx.Timer.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) initializeTranslator() {
|
||||
ctx.Translator = translator.New(ctx.Cfg)
|
||||
ctx.Translator.Initialize()
|
||||
ctx.Translator = translator.New(ctx.Cfg)
|
||||
ctx.Translator.Initialize()
|
||||
}
|
||||
|
||||
func (ctx *Context) Initialize() {
|
||||
fmt.Println("Initializing application context...")
|
||||
ctx.initializeColorizer()
|
||||
ctx.initializeConfig()
|
||||
ctx.initializeDatabase()
|
||||
ctx.initializeTranslator()
|
||||
ctx.initializeEventer()
|
||||
ctx.initializeCache()
|
||||
ctx.initializeLauncher()
|
||||
ctx.initializeTimer()
|
||||
ctx.initializeRequester()
|
||||
fmt.Println("Initializing application context...")
|
||||
ctx.initializeColorizer()
|
||||
ctx.initializeConfig()
|
||||
ctx.initializeDatabase()
|
||||
ctx.initializeTranslator()
|
||||
ctx.initializeEventer()
|
||||
ctx.initializeCache()
|
||||
ctx.initializeLauncher()
|
||||
ctx.initializeTimer()
|
||||
ctx.initializeRequester()
|
||||
}
|
||||
|
@ -10,85 +10,84 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
//"database/sql"
|
||||
"fmt"
|
||||
"path"
|
||||
"runtime"
|
||||
"strconv"
|
||||
// stdlib
|
||||
//"database/sql"
|
||||
"fmt"
|
||||
"path"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/configuration"
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/configuration"
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
|
||||
// Other
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
// Other
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
// Configuration.
|
||||
cfg *configuration.Config
|
||||
// Pointer to initialized database connection.
|
||||
Db *sqlx.DB
|
||||
// Configuration.
|
||||
cfg *configuration.Config
|
||||
// Pointer to initialized database connection.
|
||||
Db *sqlx.DB
|
||||
}
|
||||
|
||||
func (d *Database) Close() {
|
||||
fmt.Println("Closing database...")
|
||||
fmt.Println("Closing database...")
|
||||
|
||||
// Save configuration.
|
||||
// Delete previous configuration.
|
||||
d.Db.MustExec("DELETE FROM configuration")
|
||||
tx := d.Db.MustBegin()
|
||||
for k, v := range cfg.Cfg {
|
||||
cfg_item := datamodels.Configuration{}
|
||||
cfg_item.Key = k
|
||||
cfg_item.Value = v
|
||||
tx.NamedExec("INSERT INTO configuration (key, value) VALUES (:key, :value)", &cfg_item)
|
||||
}
|
||||
tx.Commit()
|
||||
// Save configuration.
|
||||
// Delete previous configuration.
|
||||
d.Db.MustExec("DELETE FROM configuration")
|
||||
tx := d.Db.MustBegin()
|
||||
for k, v := range cfg.Cfg {
|
||||
cfg_item := datamodels.Configuration{}
|
||||
cfg_item.Key = k
|
||||
cfg_item.Value = v
|
||||
tx.NamedExec("INSERT INTO configuration (key, value) VALUES (:key, :value)", &cfg_item)
|
||||
}
|
||||
tx.Commit()
|
||||
|
||||
d.Db.Close()
|
||||
d.Db.Close()
|
||||
|
||||
runtime.UnlockOSThread()
|
||||
runtime.UnlockOSThread()
|
||||
}
|
||||
|
||||
func (d *Database) Initialize(cfg *configuration.Config) {
|
||||
fmt.Println("Initializing database...")
|
||||
fmt.Println("Initializing database...")
|
||||
|
||||
runtime.LockOSThread()
|
||||
runtime.LockOSThread()
|
||||
|
||||
// Connect to database.
|
||||
db_path := path.Join(cfg.TEMP["DATA"], "database.sqlite3")
|
||||
fmt.Println("Database path: " + db_path)
|
||||
db, err := sqlx.Connect("sqlite3", db_path)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
d.Db = db
|
||||
// Connect to database.
|
||||
db_path := path.Join(cfg.TEMP["DATA"], "database.sqlite3")
|
||||
fmt.Println("Database path: " + db_path)
|
||||
db, err := sqlx.Connect("sqlite3", db_path)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
d.Db = db
|
||||
|
||||
// Load configuration.
|
||||
cfgs := []datamodels.Configuration{}
|
||||
d.Db.Select(&cfgs, "SELECT * FROM configuration")
|
||||
if len(cfgs) > 0 {
|
||||
for i := range cfgs {
|
||||
cfg.Cfg[cfgs[i].Key] = cfgs[i].Value
|
||||
}
|
||||
}
|
||||
// Load configuration.
|
||||
cfgs := []datamodels.Configuration{}
|
||||
d.Db.Select(&cfgs, "SELECT * FROM configuration")
|
||||
if len(cfgs) > 0 {
|
||||
for i := range cfgs {
|
||||
cfg.Cfg[cfgs[i].Key] = cfgs[i].Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Database) Migrate() {
|
||||
// Getting current database version.
|
||||
dbver := 0
|
||||
database := []datamodels.Database{}
|
||||
d.Db.Select(&database, "SELECT * FROM database")
|
||||
if len(database) > 0 {
|
||||
fmt.Println("Current database version: " + database[0].Version)
|
||||
dbver, _ = strconv.Atoi(database[0].Version)
|
||||
} else {
|
||||
fmt.Println("No database found, will create new one")
|
||||
}
|
||||
// Getting current database version.
|
||||
dbver := 0
|
||||
database := []datamodels.Database{}
|
||||
d.Db.Select(&database, "SELECT * FROM database")
|
||||
if len(database) > 0 {
|
||||
fmt.Println("Current database version: " + database[0].Version)
|
||||
dbver, _ = strconv.Atoi(database[0].Version)
|
||||
} else {
|
||||
fmt.Println("No database found, will create new one")
|
||||
}
|
||||
|
||||
|
||||
migrate_full(d, dbver)
|
||||
migrate_full(d, dbver)
|
||||
}
|
||||
|
@ -10,16 +10,16 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
// Local
|
||||
"github.com/pztrn/urtrator/configuration"
|
||||
// Local
|
||||
"gitlab.com/pztrn/urtrator/configuration"
|
||||
)
|
||||
|
||||
var (
|
||||
cfg *configuration.Config
|
||||
cfg *configuration.Config
|
||||
)
|
||||
|
||||
func New(c *configuration.Config) *Database {
|
||||
cfg = c
|
||||
d := Database{}
|
||||
return &d
|
||||
cfg = c
|
||||
d := Database{}
|
||||
return &d
|
||||
}
|
||||
|
@ -51,14 +51,14 @@ fi
|
||||
|
||||
# Okay, let's compile.
|
||||
echo "Getting URTrator (and dependencies) sources"
|
||||
go get -u -v -d github.com/pztrn/urtrator
|
||||
go get -u -v -d gitlab.com/pztrn/urtrator
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to get URTrator sources"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Building URTrator..."
|
||||
go install -v github.com/pztrn/urtrator
|
||||
go install -v gitlab.com/pztrn/urtrator
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to build URTrator! Please, create a new bug report at https://github.com/pztrn/urtrator and attach FULL console output!"
|
||||
exit 1
|
||||
@ -69,7 +69,7 @@ mkdir -p URTrator.app/Contents/{MacOS,Framework,Resources}
|
||||
# Copying URTrator binary
|
||||
cp $GOPATH/bin/urtrator URTrator.app/Contents/MacOS/
|
||||
# Copying main resources.
|
||||
cp $GOPATH/src/github.com/pztrn/urtrator/artwork/urtrator.icns ./URTrator.app/Contents/Resources/
|
||||
cp $GOPATH/src/gitlab.com/pztrn/urtrator/artwork/urtrator.icns ./URTrator.app/Contents/Resources/
|
||||
cp -R ./Resources/themes ./URTrator.app/Contents/Resources/
|
||||
|
||||
#####################################################################
|
||||
@ -90,7 +90,7 @@ INFOPLIST='<?xml version="1.0" encoding="UTF-8"?>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>urtrator.icns</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.0</string>
|
||||
<string>0.2.0</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
@ -10,128 +10,128 @@
|
||||
package launcher
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
// stdlib
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
|
||||
// Github
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
// Github
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
)
|
||||
|
||||
type Launcher struct {
|
||||
// Flags.
|
||||
// Is Urban Terror launched ATM?
|
||||
launched bool
|
||||
// Flags.
|
||||
// Is Urban Terror launched ATM?
|
||||
launched bool
|
||||
}
|
||||
|
||||
func (l *Launcher) CheckForLaunchedUrbanTerror() error {
|
||||
if l.launched {
|
||||
// Temporary disable all these modals on Linux.
|
||||
// See https://github.com/mattn/go-gtk/issues/289.
|
||||
if runtime.GOOS != "linux" {
|
||||
mbox_string := "Game is launched.\n\nCannot quit, because game is launched.\nQuit Urban Terror to exit URTrator!"
|
||||
m := gtk.NewMessageDialog(nil, 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.")
|
||||
}
|
||||
}
|
||||
if l.launched {
|
||||
// Temporary disable all these modals on Linux.
|
||||
// See https://github.com/mattn/go-gtk/issues/289.
|
||||
if runtime.GOOS != "linux" {
|
||||
mbox_string := "Game is launched.\n\nCannot quit, because game is launched.\nQuit Urban Terror to exit URTrator!"
|
||||
m := gtk.NewMessageDialog(nil, 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.")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Launcher) findFreeDisplay() string {
|
||||
current_display_raw := os.Getenv("DISPLAY")
|
||||
current_display, _ := strconv.Atoi(strings.Split(current_display_raw, ":")[1])
|
||||
current_display += 1
|
||||
return strconv.Itoa(current_display)
|
||||
current_display_raw := os.Getenv("DISPLAY")
|
||||
current_display, _ := strconv.Atoi(strings.Split(current_display_raw, ":")[1])
|
||||
current_display += 1
|
||||
return strconv.Itoa(current_display)
|
||||
}
|
||||
|
||||
func (l *Launcher) Initialize() {
|
||||
fmt.Println("Initializing game launcher...")
|
||||
fmt.Println("Initializing game launcher...")
|
||||
}
|
||||
|
||||
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
|
||||
// should be disabled.
|
||||
fmt.Println("Launching Urban Terror...")
|
||||
// ToDo: only one instance of Urban Terror should be launched, so button
|
||||
// should be disabled.
|
||||
fmt.Println("Launching Urban Terror...")
|
||||
|
||||
done := make(chan bool, 1)
|
||||
done := make(chan bool, 1)
|
||||
|
||||
// Create launch string.
|
||||
var launch_bin string = ""
|
||||
launch_bin, err := exec.LookPath(user_profile.Binary)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
// Create launch string.
|
||||
var launch_bin string = ""
|
||||
launch_bin, err := exec.LookPath(user_profile.Binary)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
|
||||
server_address := server_profile.Ip + ":" + server_profile.Port
|
||||
server_address := server_profile.Ip + ":" + server_profile.Port
|
||||
|
||||
var launch_params []string
|
||||
if len(server_address) > 0 {
|
||||
launch_params = append(launch_params, "+connect", server_address)
|
||||
}
|
||||
if len(password) > 0 {
|
||||
launch_params = append(launch_params, "+password", password)
|
||||
}
|
||||
if len(user_profile.Additional_params) > 0 {
|
||||
additional_params := strings.Split(user_profile.Additional_params, " ")
|
||||
launch_params = append(launch_params, additional_params...)
|
||||
}
|
||||
if len(additional_parameters) > 0 {
|
||||
for i := range additional_parameters {
|
||||
launch_params = append(launch_params, additional_parameters[i])
|
||||
}
|
||||
}
|
||||
if runtime.GOOS == "linux" && user_profile.Second_x_session == "1" {
|
||||
launch_params = append([]string{launch_bin}, launch_params...)
|
||||
display := l.findFreeDisplay()
|
||||
launch_bin, err = exec.LookPath("xinit")
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
launch_params = append(launch_params, "--", ":" + display)
|
||||
}
|
||||
if runtime.GOOS == "darwin" {
|
||||
// On macOS we should not start binary, but application bundle.
|
||||
// So we will obtain app bundle path.
|
||||
bundle_path := strings.Split(launch_bin, "/Contents")[0]
|
||||
// and create special launch string, which involves open.
|
||||
launch_bin = "/usr/bin/open"
|
||||
launch_params = append([]string{launch_bin, "-W", "-a", bundle_path, "--args"}, launch_params...)
|
||||
}
|
||||
fmt.Println(launch_bin, launch_params)
|
||||
go func() {
|
||||
go func() {
|
||||
cmd := exec.Command(launch_bin, launch_params...)
|
||||
// This workaround is required on Windows, otherwise ioq3
|
||||
// will not find game data.
|
||||
if runtime.GOOS == "windows" {
|
||||
dir := filepath.Dir(launch_bin)
|
||||
cmd.Dir = dir
|
||||
}
|
||||
out, err1 := cmd.Output()
|
||||
if err1 != nil {
|
||||
fmt.Println("Launch error: " + err1.Error())
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
done <- true
|
||||
}()
|
||||
var launch_params []string
|
||||
if len(server_address) > 0 {
|
||||
launch_params = append(launch_params, "+connect", server_address)
|
||||
}
|
||||
if len(password) > 0 {
|
||||
launch_params = append(launch_params, "+password", password)
|
||||
}
|
||||
if len(user_profile.Additional_params) > 0 {
|
||||
additional_params := strings.Split(user_profile.Additional_params, " ")
|
||||
launch_params = append(launch_params, additional_params...)
|
||||
}
|
||||
if len(additional_parameters) > 0 {
|
||||
for i := range additional_parameters {
|
||||
launch_params = append(launch_params, additional_parameters[i])
|
||||
}
|
||||
}
|
||||
if runtime.GOOS == "linux" && user_profile.Second_x_session == "1" {
|
||||
launch_params = append([]string{launch_bin}, launch_params...)
|
||||
display := l.findFreeDisplay()
|
||||
launch_bin, err = exec.LookPath("xinit")
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
launch_params = append(launch_params, "--", ":"+display)
|
||||
}
|
||||
if runtime.GOOS == "darwin" {
|
||||
// On macOS we should not start binary, but application bundle.
|
||||
// So we will obtain app bundle path.
|
||||
bundle_path := strings.Split(launch_bin, "/Contents")[0]
|
||||
// and create special launch string, which involves open.
|
||||
launch_bin = "/usr/bin/open"
|
||||
launch_params = append([]string{launch_bin, "-W", "-a", bundle_path, "--args"}, launch_params...)
|
||||
}
|
||||
fmt.Println(launch_bin, launch_params)
|
||||
go func() {
|
||||
go func() {
|
||||
cmd := exec.Command(launch_bin, launch_params...)
|
||||
// This workaround is required on Windows, otherwise ioq3
|
||||
// will not find game data.
|
||||
if runtime.GOOS == "windows" {
|
||||
dir := filepath.Dir(launch_bin)
|
||||
cmd.Dir = dir
|
||||
}
|
||||
out, err1 := cmd.Output()
|
||||
if err1 != nil {
|
||||
fmt.Println("Launch error: " + err1.Error())
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
done <- true
|
||||
}()
|
||||
|
||||
select {
|
||||
case <- done:
|
||||
callback()
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case <-done:
|
||||
callback()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -10,29 +10,29 @@
|
||||
package requester
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
// stdlib
|
||||
"fmt"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/cache"
|
||||
"github.com/pztrn/urtrator/configuration"
|
||||
"github.com/pztrn/urtrator/eventer"
|
||||
"github.com/pztrn/urtrator/timer"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/cache"
|
||||
"gitlab.com/pztrn/urtrator/configuration"
|
||||
"gitlab.com/pztrn/urtrator/eventer"
|
||||
"gitlab.com/pztrn/urtrator/timer"
|
||||
)
|
||||
|
||||
var (
|
||||
Cache *cache.Cache
|
||||
Cfg *configuration.Config
|
||||
Eventer *eventer.Eventer
|
||||
Timer *timer.Timer
|
||||
Cache *cache.Cache
|
||||
Cfg *configuration.Config
|
||||
Eventer *eventer.Eventer
|
||||
Timer *timer.Timer
|
||||
)
|
||||
|
||||
func New(c *cache.Cache, e *eventer.Eventer, cc *configuration.Config, t *timer.Timer) *Requester {
|
||||
Cache = c
|
||||
Cfg = cc
|
||||
Eventer = e
|
||||
Timer = t
|
||||
fmt.Println("Creating Requester object...")
|
||||
r := Requester{}
|
||||
return &r
|
||||
Cache = c
|
||||
Cfg = cc
|
||||
Eventer = e
|
||||
Timer = t
|
||||
fmt.Println("Creating Requester object...")
|
||||
r := Requester{}
|
||||
return &r
|
||||
}
|
||||
|
@ -10,281 +10,281 @@
|
||||
package requester
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
// stdlib
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
)
|
||||
|
||||
type Pooler struct {
|
||||
// Maximum number of simultaneous requests running.
|
||||
maxrequests int
|
||||
// Packet prefix.
|
||||
pp string
|
||||
// Current requests counter mutex.
|
||||
cur_requests_mutex sync.Mutex
|
||||
// Maximum number of simultaneous requests running.
|
||||
maxrequests int
|
||||
// Packet prefix.
|
||||
pp string
|
||||
// Current requests counter mutex.
|
||||
cur_requests_mutex sync.Mutex
|
||||
}
|
||||
|
||||
func (p *Pooler) Initialize() {
|
||||
fmt.Println("Initializing requester goroutine pooler...")
|
||||
// ToDo: figure out how to make this work nice.
|
||||
p.maxrequests = 150
|
||||
_ = runtime.GOMAXPROCS(runtime.NumCPU() * 4)
|
||||
p.pp = "\377\377\377\377"
|
||||
fmt.Println("Pooler initialized")
|
||||
fmt.Println("Initializing requester goroutine pooler...")
|
||||
// ToDo: figure out how to make this work nice.
|
||||
p.maxrequests = 150
|
||||
_ = runtime.GOMAXPROCS(runtime.NumCPU() * 4)
|
||||
p.pp = "\377\377\377\377"
|
||||
fmt.Println("Pooler initialized")
|
||||
}
|
||||
|
||||
func (p *Pooler) PingOneServer(server_address string) {
|
||||
var wait sync.WaitGroup
|
||||
var wait sync.WaitGroup
|
||||
|
||||
Cache.ServersMutex.Lock()
|
||||
server := Cache.Servers[server_address].Server
|
||||
Cache.ServersMutex.Unlock()
|
||||
Cache.ServersMutex.Lock()
|
||||
server := Cache.Servers[server_address].Server
|
||||
Cache.ServersMutex.Unlock()
|
||||
|
||||
wait.Add(1)
|
||||
go func(srv *datamodels.Server) {
|
||||
defer wait.Done()
|
||||
p.pingServersExecutor(srv)
|
||||
}(server)
|
||||
wait.Wait()
|
||||
wait.Add(1)
|
||||
go func(srv *datamodels.Server) {
|
||||
defer wait.Done()
|
||||
p.pingServersExecutor(srv)
|
||||
}(server)
|
||||
wait.Wait()
|
||||
}
|
||||
|
||||
// Servers pinging pooler. Should be started as goroutine to prevent
|
||||
// UI blocking.
|
||||
func (p *Pooler) PingServers(servers_type string) {
|
||||
fmt.Println("About to ping " + servers_type + " servers...")
|
||||
fmt.Println("About to ping " + servers_type + " servers...")
|
||||
|
||||
cur_requests := 0
|
||||
var wait sync.WaitGroup
|
||||
cur_requests := 0
|
||||
var wait sync.WaitGroup
|
||||
|
||||
Cache.ServersMutex.Lock()
|
||||
for _, server_to_ping := range Cache.Servers {
|
||||
if servers_type == "favorites" && server_to_ping.Server.Favorite != "1" {
|
||||
continue
|
||||
}
|
||||
for {
|
||||
p.cur_requests_mutex.Lock()
|
||||
if cur_requests == p.maxrequests {
|
||||
p.cur_requests_mutex.Unlock()
|
||||
time.Sleep(time.Second * 1)
|
||||
} else {
|
||||
p.cur_requests_mutex.Unlock()
|
||||
break
|
||||
}
|
||||
}
|
||||
wait.Add(1)
|
||||
p.cur_requests_mutex.Lock()
|
||||
cur_requests += 1
|
||||
p.cur_requests_mutex.Unlock()
|
||||
go func(srv *datamodels.Server) {
|
||||
defer wait.Done()
|
||||
p.pingServersExecutor(srv)
|
||||
p.cur_requests_mutex.Lock()
|
||||
cur_requests -= 1
|
||||
p.cur_requests_mutex.Unlock()
|
||||
}(server_to_ping.Server)
|
||||
}
|
||||
wait.Wait()
|
||||
Cache.ServersMutex.Unlock()
|
||||
Cache.ServersMutex.Lock()
|
||||
for _, server_to_ping := range Cache.Servers {
|
||||
if servers_type == "favorites" && server_to_ping.Server.Favorite != "1" {
|
||||
continue
|
||||
}
|
||||
for {
|
||||
p.cur_requests_mutex.Lock()
|
||||
if cur_requests == p.maxrequests {
|
||||
p.cur_requests_mutex.Unlock()
|
||||
time.Sleep(time.Second * 1)
|
||||
} else {
|
||||
p.cur_requests_mutex.Unlock()
|
||||
break
|
||||
}
|
||||
}
|
||||
wait.Add(1)
|
||||
p.cur_requests_mutex.Lock()
|
||||
cur_requests += 1
|
||||
p.cur_requests_mutex.Unlock()
|
||||
go func(srv *datamodels.Server) {
|
||||
defer wait.Done()
|
||||
p.pingServersExecutor(srv)
|
||||
p.cur_requests_mutex.Lock()
|
||||
cur_requests -= 1
|
||||
p.cur_requests_mutex.Unlock()
|
||||
}(server_to_ping.Server)
|
||||
}
|
||||
wait.Wait()
|
||||
Cache.ServersMutex.Unlock()
|
||||
}
|
||||
|
||||
func (p *Pooler) pingServersExecutor(server *datamodels.Server) error {
|
||||
srv := server.Ip + ":" + server.Port
|
||||
fmt.Println("Pinging " + srv)
|
||||
// Dial to server.
|
||||
start_p := time.Now()
|
||||
conn_ping, err2 := net.Dial("udp", srv)
|
||||
if err2 != nil {
|
||||
fmt.Println("Error dialing to server " + srv + "!")
|
||||
return errors.New("Error dialing to server " + srv + "!")
|
||||
}
|
||||
// Set deadline, so we won't wait forever.
|
||||
ddl_ping := time.Now()
|
||||
// This should be enough. Maybe, you should'n run URTrator on modem
|
||||
// connections? :)
|
||||
ddl_ping = ddl_ping.Add(time.Second * 10)
|
||||
conn_ping.SetDeadline(ddl_ping)
|
||||
srv := server.Ip + ":" + server.Port
|
||||
fmt.Println("Pinging " + srv)
|
||||
// Dial to server.
|
||||
start_p := time.Now()
|
||||
conn_ping, err2 := net.Dial("udp", srv)
|
||||
if err2 != nil {
|
||||
fmt.Println("Error dialing to server " + srv + "!")
|
||||
return errors.New("Error dialing to server " + srv + "!")
|
||||
}
|
||||
// Set deadline, so we won't wait forever.
|
||||
ddl_ping := time.Now()
|
||||
// This should be enough. Maybe, you should'n run URTrator on modem
|
||||
// connections? :)
|
||||
ddl_ping = ddl_ping.Add(time.Second * 10)
|
||||
conn_ping.SetDeadline(ddl_ping)
|
||||
|
||||
msg_ping := []byte(p.pp + "getinfo")
|
||||
conn_ping.Write(msg_ping)
|
||||
msg_ping := []byte(p.pp + "getinfo")
|
||||
conn_ping.Write(msg_ping)
|
||||
|
||||
// UDP Buffer.
|
||||
var received_buf_ping []byte = make([]byte, 128)
|
||||
// Received buffer.
|
||||
var raw_received_ping []byte
|
||||
_, err := conn_ping.Read(received_buf_ping)
|
||||
if err != nil {
|
||||
fmt.Println("PING ERROR")
|
||||
}
|
||||
raw_received_ping = append(raw_received_ping, received_buf_ping...)
|
||||
conn_ping.Close()
|
||||
// UDP Buffer.
|
||||
var received_buf_ping []byte = make([]byte, 128)
|
||||
// Received buffer.
|
||||
var raw_received_ping []byte
|
||||
_, err := conn_ping.Read(received_buf_ping)
|
||||
if err != nil {
|
||||
fmt.Println("PING ERROR")
|
||||
}
|
||||
raw_received_ping = append(raw_received_ping, received_buf_ping...)
|
||||
conn_ping.Close()
|
||||
|
||||
delta := strconv.Itoa(int(time.Since(start_p).Nanoseconds()) / 1000000)
|
||||
server.Ping = delta
|
||||
delta := strconv.Itoa(int(time.Since(start_p).Nanoseconds()) / 1000000)
|
||||
server.Ping = delta
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pooler) UpdateOneServer(server_address string) {
|
||||
var wait sync.WaitGroup
|
||||
var wait sync.WaitGroup
|
||||
|
||||
Cache.ServersMutex.Lock()
|
||||
server := Cache.Servers[server_address].Server
|
||||
Cache.ServersMutex.Unlock()
|
||||
Cache.ServersMutex.Lock()
|
||||
server := Cache.Servers[server_address].Server
|
||||
Cache.ServersMutex.Unlock()
|
||||
|
||||
wait.Add(1)
|
||||
go func(server *datamodels.Server) {
|
||||
defer wait.Done()
|
||||
p.UpdateSpecificServer(server)
|
||||
}(server)
|
||||
wait.Wait()
|
||||
p.PingOneServer(server_address)
|
||||
Eventer.LaunchEvent("flushServers", map[string]string{})
|
||||
wait.Add(1)
|
||||
go func(server *datamodels.Server) {
|
||||
defer wait.Done()
|
||||
p.UpdateSpecificServer(server)
|
||||
}(server)
|
||||
wait.Wait()
|
||||
p.PingOneServer(server_address)
|
||||
Eventer.LaunchEvent("flushServers", map[string]string{})
|
||||
|
||||
Eventer.LaunchEvent("loadAllServers", map[string]string{})
|
||||
Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
|
||||
Eventer.LaunchEvent("serversUpdateCompleted", map[string]string{})
|
||||
Eventer.LaunchEvent("loadAllServers", map[string]string{})
|
||||
Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
|
||||
Eventer.LaunchEvent("serversUpdateCompleted", map[string]string{})
|
||||
}
|
||||
|
||||
func (p *Pooler) UpdateServers(servers_type string) {
|
||||
var wait sync.WaitGroup
|
||||
var wait sync.WaitGroup
|
||||
|
||||
Cache.ServersMutex.Lock()
|
||||
for _, server := range Cache.Servers {
|
||||
if servers_type == "favorites" && server.Server.Favorite != "1" {
|
||||
continue
|
||||
}
|
||||
wait.Add(1)
|
||||
go func(server *datamodels.Server) {
|
||||
defer wait.Done()
|
||||
p.UpdateSpecificServer(server)
|
||||
}(server.Server)
|
||||
}
|
||||
wait.Wait()
|
||||
Cache.ServersMutex.Unlock()
|
||||
p.PingServers(servers_type)
|
||||
Eventer.LaunchEvent("flushServers", map[string]string{})
|
||||
Cache.ServersMutex.Lock()
|
||||
for _, server := range Cache.Servers {
|
||||
if servers_type == "favorites" && server.Server.Favorite != "1" {
|
||||
continue
|
||||
}
|
||||
wait.Add(1)
|
||||
go func(server *datamodels.Server) {
|
||||
defer wait.Done()
|
||||
p.UpdateSpecificServer(server)
|
||||
}(server.Server)
|
||||
}
|
||||
wait.Wait()
|
||||
Cache.ServersMutex.Unlock()
|
||||
p.PingServers(servers_type)
|
||||
Eventer.LaunchEvent("flushServers", map[string]string{})
|
||||
|
||||
Eventer.LaunchEvent("loadAllServers", map[string]string{})
|
||||
Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
|
||||
Eventer.LaunchEvent("serversUpdateCompleted", map[string]string{})
|
||||
Eventer.LaunchEvent("loadAllServers", map[string]string{})
|
||||
Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
|
||||
Eventer.LaunchEvent("serversUpdateCompleted", map[string]string{})
|
||||
}
|
||||
|
||||
// Updates information about specific server.
|
||||
func (p *Pooler) UpdateSpecificServer(server *datamodels.Server) error {
|
||||
server_addr := server.Ip + ":" + server.Port
|
||||
fmt.Println("Updating server: " + server_addr)
|
||||
server_addr := server.Ip + ":" + server.Port
|
||||
fmt.Println("Updating server: " + server_addr)
|
||||
|
||||
// Dial to server.
|
||||
conn, err1 := net.Dial("udp", server_addr)
|
||||
if err1 != nil {
|
||||
fmt.Println("Error dialing to server " + server_addr + "!")
|
||||
return errors.New("Error dialing to server " + server_addr + "!")
|
||||
}
|
||||
// Dial to server.
|
||||
conn, err1 := net.Dial("udp", server_addr)
|
||||
if err1 != nil {
|
||||
fmt.Println("Error dialing to server " + server_addr + "!")
|
||||
return errors.New("Error dialing to server " + server_addr + "!")
|
||||
}
|
||||
|
||||
// Set deadline, so we won't wait forever.
|
||||
ddl := time.Now()
|
||||
// This should be enough. Maybe, you should'n run URTrator on modem
|
||||
// connections? :)
|
||||
ddl = ddl.Add(time.Second * 2)
|
||||
conn.SetDeadline(ddl)
|
||||
// Set deadline, so we won't wait forever.
|
||||
ddl := time.Now()
|
||||
// This should be enough. Maybe, you should'n run URTrator on modem
|
||||
// connections? :)
|
||||
ddl = ddl.Add(time.Second * 2)
|
||||
conn.SetDeadline(ddl)
|
||||
|
||||
msg := []byte(p.pp + "getstatus")
|
||||
conn.Write(msg)
|
||||
msg := []byte(p.pp + "getstatus")
|
||||
conn.Write(msg)
|
||||
|
||||
// UDP Buffer.
|
||||
var received_buf []byte = make([]byte, 4096)
|
||||
// Received buffer.
|
||||
var raw_received []byte
|
||||
for {
|
||||
_, err := conn.Read(received_buf)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
raw_received = append(raw_received, received_buf...)
|
||||
}
|
||||
conn.Close()
|
||||
// UDP Buffer.
|
||||
var received_buf []byte = make([]byte, 4096)
|
||||
// Received buffer.
|
||||
var raw_received []byte
|
||||
for {
|
||||
_, err := conn.Read(received_buf)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
raw_received = append(raw_received, received_buf...)
|
||||
}
|
||||
conn.Close()
|
||||
|
||||
// First line is "infoResponse" string, which we should skip by
|
||||
// splitting response by "\n".
|
||||
received_lines := strings.Split(string(raw_received), "\n")
|
||||
// We have server's data!
|
||||
if len(received_lines) > 1 {
|
||||
srv_config := strings.Split(received_lines[1], "\\")
|
||||
// Parse server configuration into passed server's datamodel.
|
||||
for i := 0; i < len(srv_config); i = i + 1 {
|
||||
if srv_config[i] == "g_modversion" {
|
||||
server.Version = srv_config[i + 1]
|
||||
}
|
||||
if srv_config[i] == "g_gametype" {
|
||||
server.Gamemode = srv_config[i + 1]
|
||||
}
|
||||
if srv_config[i] == "sv_maxclients" {
|
||||
server.Maxplayers = srv_config[i + 1]
|
||||
}
|
||||
if srv_config[i] == "clients" {
|
||||
server.Players = srv_config[i + 1]
|
||||
}
|
||||
if srv_config[i] == "mapname" {
|
||||
server.Map = srv_config[i + 1]
|
||||
}
|
||||
if srv_config[i] == "sv_hostname" {
|
||||
server.Name = srv_config[i + 1]
|
||||
}
|
||||
if srv_config[i] == "g_needpass" {
|
||||
if srv_config[i + 1] == "0" {
|
||||
server.IsPrivate = "0"
|
||||
} else {
|
||||
server.IsPrivate = "1"
|
||||
}
|
||||
}
|
||||
server.ExtendedConfig = received_lines[1]
|
||||
}
|
||||
if len(received_lines) >= 2 {
|
||||
// Here we go, players information.
|
||||
players := received_lines[2:]
|
||||
var real_players int = 0
|
||||
var bots int = 0
|
||||
// Calculate players!
|
||||
if len(players) == 1 && len(players[0]) > 255 {
|
||||
server.Players = "0"
|
||||
server.Bots = "0"
|
||||
} else {
|
||||
// Looks like we have last element to be empty, due to
|
||||
// strings.Split() call before.
|
||||
for i := range players {
|
||||
// Get slice with data for bots-humans parsing.
|
||||
player_data := strings.Split(string(players[i]), " ")
|
||||
// If slice length isn't equal 3 - this is not what
|
||||
// we want.
|
||||
if len(player_data) != 3 {
|
||||
continue
|
||||
}
|
||||
// First line is "infoResponse" string, which we should skip by
|
||||
// splitting response by "\n".
|
||||
received_lines := strings.Split(string(raw_received), "\n")
|
||||
// We have server's data!
|
||||
if len(received_lines) > 1 {
|
||||
srv_config := strings.Split(received_lines[1], "\\")
|
||||
// Parse server configuration into passed server's datamodel.
|
||||
for i := 0; i < len(srv_config); i = i + 1 {
|
||||
if srv_config[i] == "g_modversion" {
|
||||
server.Version = srv_config[i+1]
|
||||
}
|
||||
if srv_config[i] == "g_gametype" {
|
||||
server.Gamemode = srv_config[i+1]
|
||||
}
|
||||
if srv_config[i] == "sv_maxclients" {
|
||||
server.Maxplayers = srv_config[i+1]
|
||||
}
|
||||
if srv_config[i] == "clients" {
|
||||
server.Players = srv_config[i+1]
|
||||
}
|
||||
if srv_config[i] == "mapname" {
|
||||
server.Map = srv_config[i+1]
|
||||
}
|
||||
if srv_config[i] == "sv_hostname" {
|
||||
server.Name = srv_config[i+1]
|
||||
}
|
||||
if srv_config[i] == "g_needpass" {
|
||||
if srv_config[i+1] == "0" {
|
||||
server.IsPrivate = "0"
|
||||
} else {
|
||||
server.IsPrivate = "1"
|
||||
}
|
||||
}
|
||||
server.ExtendedConfig = received_lines[1]
|
||||
}
|
||||
if len(received_lines) >= 2 {
|
||||
// Here we go, players information.
|
||||
players := received_lines[2:]
|
||||
var real_players int = 0
|
||||
var bots int = 0
|
||||
// Calculate players!
|
||||
if len(players) == 1 && len(players[0]) > 255 {
|
||||
server.Players = "0"
|
||||
server.Bots = "0"
|
||||
} else {
|
||||
// Looks like we have last element to be empty, due to
|
||||
// strings.Split() call before.
|
||||
for i := range players {
|
||||
// Get slice with data for bots-humans parsing.
|
||||
player_data := strings.Split(string(players[i]), " ")
|
||||
// If slice length isn't equal 3 - this is not what
|
||||
// we want.
|
||||
if len(player_data) != 3 {
|
||||
continue
|
||||
}
|
||||
|
||||
if player_data[1] == "0" {
|
||||
bots++
|
||||
} else {
|
||||
real_players++
|
||||
}
|
||||
}
|
||||
//server.Players = strconv.Itoa(len(players) - 1)
|
||||
server.Players = strconv.Itoa(real_players)
|
||||
server.Bots = strconv.Itoa(bots)
|
||||
fmt.Println(server.Players, server.Bots)
|
||||
}
|
||||
server.PlayersInfo = strings.Join(received_lines[2:], "\\")
|
||||
}
|
||||
}
|
||||
if player_data[1] == "0" {
|
||||
bots++
|
||||
} else {
|
||||
real_players++
|
||||
}
|
||||
}
|
||||
//server.Players = strconv.Itoa(len(players) - 1)
|
||||
server.Players = strconv.Itoa(real_players)
|
||||
server.Bots = strconv.Itoa(bots)
|
||||
fmt.Println(server.Players, server.Bots)
|
||||
}
|
||||
server.PlayersInfo = strings.Join(received_lines[2:], "\\")
|
||||
}
|
||||
}
|
||||
|
||||
// ToDo: Calculate ping. 0 for now.
|
||||
server.Ping = "0"
|
||||
return nil
|
||||
// ToDo: Calculate ping. 0 for now.
|
||||
server.Ping = "0"
|
||||
return nil
|
||||
}
|
||||
|
@ -10,23 +10,23 @@
|
||||
package timer
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
// stdlib
|
||||
"fmt"
|
||||
|
||||
// local
|
||||
"github.com/pztrn/urtrator/configuration"
|
||||
"github.com/pztrn/urtrator/eventer"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/configuration"
|
||||
"gitlab.com/pztrn/urtrator/eventer"
|
||||
)
|
||||
|
||||
var (
|
||||
Cfg *configuration.Config
|
||||
Eventer *eventer.Eventer
|
||||
Cfg *configuration.Config
|
||||
Eventer *eventer.Eventer
|
||||
)
|
||||
|
||||
func New(e *eventer.Eventer, cc *configuration.Config) *Timer {
|
||||
Cfg = cc
|
||||
Eventer = e
|
||||
fmt.Println("Creating Timer object...")
|
||||
t := Timer{}
|
||||
return &t
|
||||
Cfg = cc
|
||||
Eventer = e
|
||||
fmt.Println("Creating Timer object...")
|
||||
t := Timer{}
|
||||
return &t
|
||||
}
|
||||
|
@ -10,17 +10,17 @@
|
||||
package translator
|
||||
|
||||
import (
|
||||
// local
|
||||
"github.com/pztrn/urtrator/configuration"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/configuration"
|
||||
)
|
||||
|
||||
var (
|
||||
// Configuration.
|
||||
cfg *configuration.Config
|
||||
// Configuration.
|
||||
cfg *configuration.Config
|
||||
)
|
||||
|
||||
func New(c *configuration.Config) *Translator {
|
||||
cfg = c
|
||||
t := Translator{}
|
||||
return &t
|
||||
cfg = c
|
||||
t := Translator{}
|
||||
return &t
|
||||
}
|
||||
|
@ -10,40 +10,40 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// local
|
||||
"github.com/pztrn/urtrator/common"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/common"
|
||||
|
||||
// other
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
// other
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
)
|
||||
|
||||
func ShowAboutDialog() {
|
||||
ad := gtk.NewAboutDialog()
|
||||
ad := gtk.NewAboutDialog()
|
||||
|
||||
ad.SetProgramName("URTrator")
|
||||
ad.SetComments(ctx.Translator.Translate("Urban Terror servers browser and game launcher", nil))
|
||||
ad.SetVersion(common.URTRATOR_VERSION)
|
||||
ad.SetWebsite("http://urtrator.pztrn.name")
|
||||
ad.SetLogo(logo)
|
||||
ad.SetProgramName("URTrator")
|
||||
ad.SetComments(ctx.Translator.Translate("Urban Terror servers browser and game launcher", nil))
|
||||
ad.SetVersion(common.URTRATOR_VERSION)
|
||||
ad.SetWebsite("https://gitlab.com/pztrn/urtrator")
|
||||
ad.SetLogo(logo)
|
||||
|
||||
// ToDo: put it in plain text files.
|
||||
var authors []string
|
||||
authors = append(authors, "Stanislav N. aka pztrn - project creator, main developer.")
|
||||
ad.SetAuthors(authors)
|
||||
// ToDo: put it in plain text files.
|
||||
var authors []string
|
||||
authors = append(authors, "Stanislav N. aka pztrn - project creator, main developer.")
|
||||
ad.SetAuthors(authors)
|
||||
|
||||
var artists []string
|
||||
artists = append(artists, "UrTConnector team, for great icons and allowing to use them.")
|
||||
ad.SetArtists(artists)
|
||||
var artists []string
|
||||
artists = append(artists, "UrTConnector team, for great icons and allowing to use them.")
|
||||
ad.SetArtists(artists)
|
||||
|
||||
var documenters []string
|
||||
documenters = append(documenters, "No one at this moment")
|
||||
ad.SetDocumenters(documenters)
|
||||
var documenters []string
|
||||
documenters = append(documenters, "No one at this moment")
|
||||
ad.SetDocumenters(documenters)
|
||||
|
||||
ad.SetCopyright("Stanislav N. aka pztrn")
|
||||
ad.SetLicense(GPL_LICENSE)
|
||||
ad.SetCopyright("Stanislav N. aka pztrn")
|
||||
ad.SetLicense(GPL_LICENSE)
|
||||
|
||||
ad.Run()
|
||||
ad.Destroy()
|
||||
ad.Run()
|
||||
ad.Destroy()
|
||||
}
|
||||
|
||||
var GPL_LICENSE = `
|
||||
|
@ -10,21 +10,21 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// local
|
||||
"github.com/pztrn/urtrator/context"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/context"
|
||||
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gdkpixbuf"
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gdkpixbuf"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx *context.Context
|
||||
ctx *context.Context
|
||||
|
||||
logo *gdkpixbuf.Pixbuf
|
||||
logo *gdkpixbuf.Pixbuf
|
||||
)
|
||||
|
||||
func NewMainWindow(c *context.Context) *MainWindow {
|
||||
ctx = c
|
||||
m := MainWindow{}
|
||||
return &m
|
||||
ctx = c
|
||||
m := MainWindow{}
|
||||
return &m
|
||||
}
|
||||
|
@ -10,283 +10,283 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
// stdlib
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
// Local
|
||||
"github.com/pztrn/urtrator/cachemodels"
|
||||
"github.com/pztrn/urtrator/common"
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// Local
|
||||
"gitlab.com/pztrn/urtrator/cachemodels"
|
||||
"gitlab.com/pztrn/urtrator/common"
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gdkpixbuf"
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gdkpixbuf"
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
)
|
||||
|
||||
type FavoriteDialog struct {
|
||||
// Widgets.
|
||||
// Dialog's window.
|
||||
window *gtk.Window
|
||||
// Main vertical box.
|
||||
vbox *gtk.VBox
|
||||
// Server name.
|
||||
server_name *gtk.Entry
|
||||
// Server address.
|
||||
server_address *gtk.Entry
|
||||
// Server password
|
||||
server_password *gtk.Entry
|
||||
// Profile.
|
||||
profile *gtk.ComboBoxText
|
||||
// Widgets.
|
||||
// Dialog's window.
|
||||
window *gtk.Window
|
||||
// Main vertical box.
|
||||
vbox *gtk.VBox
|
||||
// Server name.
|
||||
server_name *gtk.Entry
|
||||
// Server address.
|
||||
server_address *gtk.Entry
|
||||
// Server password
|
||||
server_password *gtk.Entry
|
||||
// Profile.
|
||||
profile *gtk.ComboBoxText
|
||||
|
||||
// Flags.
|
||||
// Is known server update performed?
|
||||
update bool
|
||||
// Flags.
|
||||
// Is known server update performed?
|
||||
update bool
|
||||
|
||||
// Data.
|
||||
// Server's we're working with.
|
||||
server *datamodels.Server
|
||||
// Profiles count that was added to profiles combobox.
|
||||
profiles int
|
||||
// Data.
|
||||
// Server's we're working with.
|
||||
server *datamodels.Server
|
||||
// Profiles count that was added to profiles combobox.
|
||||
profiles int
|
||||
}
|
||||
|
||||
func (f *FavoriteDialog) Close() {}
|
||||
|
||||
func (f *FavoriteDialog) closeByCancel() {
|
||||
f.window.Destroy()
|
||||
f.window.Destroy()
|
||||
}
|
||||
|
||||
func (f *FavoriteDialog) fill() {
|
||||
f.server_name.SetText(f.server.Name)
|
||||
f.server_address.SetText(f.server.Ip + ":" + f.server.Port)
|
||||
f.server_password.SetText(f.server.Password)
|
||||
f.server_name.SetText(f.server.Name)
|
||||
f.server_address.SetText(f.server.Ip + ":" + f.server.Port)
|
||||
f.server_password.SetText(f.server.Password)
|
||||
|
||||
// Profiles.
|
||||
// Remove old profiles.
|
||||
if f.profiles > 0 {
|
||||
for i := 0; i <= f.profiles; i++ {
|
||||
f.profile.RemoveText(0)
|
||||
}
|
||||
}
|
||||
// Profiles.
|
||||
// Remove old profiles.
|
||||
if f.profiles > 0 {
|
||||
for i := 0; i <= f.profiles; i++ {
|
||||
f.profile.RemoveText(0)
|
||||
}
|
||||
}
|
||||
|
||||
profiles := []datamodels.Profile{}
|
||||
err := ctx.Database.Db.Select(&profiles, "SELECT * FROM urt_profiles")
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
var idx_in_combobox int = 0
|
||||
var idx_should_be_active int = 0
|
||||
for p := range profiles {
|
||||
if profiles[p].Version == f.server.Version {
|
||||
f.profile.AppendText(profiles[p].Name)
|
||||
idx_should_be_active = idx_in_combobox
|
||||
idx_in_combobox += 1
|
||||
f.profiles += 1
|
||||
}
|
||||
}
|
||||
profiles := []datamodels.Profile{}
|
||||
err := ctx.Database.Db.Select(&profiles, "SELECT * FROM urt_profiles")
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
var idx_in_combobox int = 0
|
||||
var idx_should_be_active int = 0
|
||||
for p := range profiles {
|
||||
if profiles[p].Version == f.server.Version {
|
||||
f.profile.AppendText(profiles[p].Name)
|
||||
idx_should_be_active = idx_in_combobox
|
||||
idx_in_combobox += 1
|
||||
f.profiles += 1
|
||||
}
|
||||
}
|
||||
|
||||
f.profile.SetActive(idx_should_be_active)
|
||||
f.profile.SetActive(idx_should_be_active)
|
||||
}
|
||||
|
||||
func (f *FavoriteDialog) InitializeNew() {
|
||||
f.update = false
|
||||
f.server = &datamodels.Server{}
|
||||
f.profiles = 0
|
||||
f.initializeWindow()
|
||||
f.update = false
|
||||
f.server = &datamodels.Server{}
|
||||
f.profiles = 0
|
||||
f.initializeWindow()
|
||||
}
|
||||
|
||||
func (f *FavoriteDialog) InitializeUpdate(server *datamodels.Server) {
|
||||
fmt.Println("Favorites updating...")
|
||||
f.update = true
|
||||
f.server = server
|
||||
f.profiles = 0
|
||||
f.initializeWindow()
|
||||
f.fill()
|
||||
fmt.Println("Favorites updating...")
|
||||
f.update = true
|
||||
f.server = server
|
||||
f.profiles = 0
|
||||
f.initializeWindow()
|
||||
f.fill()
|
||||
}
|
||||
|
||||
func (f *FavoriteDialog) initializeWindow() {
|
||||
f.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
|
||||
if f.update {
|
||||
f.window.SetTitle(ctx.Translator.Translate("URTrator - {{ action }} favorite server", map[string]string{"action": "Update"}))
|
||||
} else {
|
||||
f.window.SetTitle(ctx.Translator.Translate("URTrator - {{ action }} favorite server", map[string]string{"action": "Add"}))
|
||||
}
|
||||
f.window.Connect("destroy", f.Close)
|
||||
f.window.SetPosition(gtk.WIN_POS_CENTER)
|
||||
f.window.SetModal(true)
|
||||
f.window.SetSizeRequest(400, 200)
|
||||
f.window.SetResizable(false)
|
||||
f.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
|
||||
if f.update {
|
||||
f.window.SetTitle(ctx.Translator.Translate("URTrator - {{ action }} favorite server", map[string]string{"action": "Update"}))
|
||||
} else {
|
||||
f.window.SetTitle(ctx.Translator.Translate("URTrator - {{ action }} favorite server", map[string]string{"action": "Add"}))
|
||||
}
|
||||
f.window.Connect("destroy", f.Close)
|
||||
f.window.SetPosition(gtk.WIN_POS_CENTER)
|
||||
f.window.SetModal(true)
|
||||
f.window.SetSizeRequest(400, 200)
|
||||
f.window.SetResizable(false)
|
||||
|
||||
// Load program icon from base64.
|
||||
icon_bytes, _ := base64.StdEncoding.DecodeString(common.Logo)
|
||||
icon_pixbuf := gdkpixbuf.NewLoader()
|
||||
icon_pixbuf.Write(icon_bytes)
|
||||
logo = icon_pixbuf.GetPixbuf()
|
||||
f.window.SetIcon(logo)
|
||||
// Load program icon from base64.
|
||||
icon_bytes, _ := base64.StdEncoding.DecodeString(common.Logo)
|
||||
icon_pixbuf := gdkpixbuf.NewLoader()
|
||||
icon_pixbuf.Write(icon_bytes)
|
||||
logo = icon_pixbuf.GetPixbuf()
|
||||
f.window.SetIcon(logo)
|
||||
|
||||
// Set some GTK options for this window.
|
||||
gtk_opts_raw := gtk.SettingsGetDefault()
|
||||
gtk_opts := gtk_opts_raw.ToGObject()
|
||||
gtk_opts.Set("gtk-button-images", true)
|
||||
// Set some GTK options for this window.
|
||||
gtk_opts_raw := gtk.SettingsGetDefault()
|
||||
gtk_opts := gtk_opts_raw.ToGObject()
|
||||
gtk_opts.Set("gtk-button-images", true)
|
||||
|
||||
f.vbox = gtk.NewVBox(false, 0)
|
||||
f.vbox = gtk.NewVBox(false, 0)
|
||||
|
||||
table := gtk.NewTable(5, 2, false)
|
||||
f.vbox.PackStart(table, true, true, 5)
|
||||
table := gtk.NewTable(5, 2, false)
|
||||
f.vbox.PackStart(table, true, true, 5)
|
||||
|
||||
// Server name.
|
||||
srv_name_label := gtk.NewLabel(ctx.Translator.Translate("Server name:", nil))
|
||||
srv_name_label.SetAlignment(0, 0)
|
||||
table.Attach(srv_name_label, 0, 1, 0, 1, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
// Server name.
|
||||
srv_name_label := gtk.NewLabel(ctx.Translator.Translate("Server name:", nil))
|
||||
srv_name_label.SetAlignment(0, 0)
|
||||
table.Attach(srv_name_label, 0, 1, 0, 1, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
|
||||
f.server_name = gtk.NewEntry()
|
||||
table.Attach(f.server_name, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
|
||||
f.server_name = gtk.NewEntry()
|
||||
table.Attach(f.server_name, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
|
||||
|
||||
// Server address.
|
||||
srv_addr_label := gtk.NewLabel(ctx.Translator.Translate("Server address:", nil))
|
||||
srv_addr_label.SetAlignment(0, 0)
|
||||
table.Attach(srv_addr_label, 0, 1, 1, 2, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
// Server address.
|
||||
srv_addr_label := gtk.NewLabel(ctx.Translator.Translate("Server address:", nil))
|
||||
srv_addr_label.SetAlignment(0, 0)
|
||||
table.Attach(srv_addr_label, 0, 1, 1, 2, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
|
||||
srv_addr_hbox := gtk.NewHBox(false, 0)
|
||||
f.server_address = gtk.NewEntry()
|
||||
srv_addr_hbox.PackStart(f.server_address, true, true, 0)
|
||||
srv_addr_update_btn := gtk.NewButton()
|
||||
srv_addr_update_btn.SetTooltipText(ctx.Translator.Translate("Update server information", nil))
|
||||
srv_addr_update_btn_image := gtk.NewImageFromStock(gtk.STOCK_REDO, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
srv_addr_update_btn.SetImage(srv_addr_update_btn_image)
|
||||
srv_addr_update_btn.Clicked(f.updateServerInfo)
|
||||
srv_addr_hbox.PackStart(srv_addr_update_btn, false, true, 5)
|
||||
if f.update {
|
||||
f.server_address.SetSensitive(false)
|
||||
}
|
||||
table.Attach(srv_addr_hbox, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5)
|
||||
srv_addr_hbox := gtk.NewHBox(false, 0)
|
||||
f.server_address = gtk.NewEntry()
|
||||
srv_addr_hbox.PackStart(f.server_address, true, true, 0)
|
||||
srv_addr_update_btn := gtk.NewButton()
|
||||
srv_addr_update_btn.SetTooltipText(ctx.Translator.Translate("Update server information", nil))
|
||||
srv_addr_update_btn_image := gtk.NewImageFromStock(gtk.STOCK_REDO, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
||||
srv_addr_update_btn.SetImage(srv_addr_update_btn_image)
|
||||
srv_addr_update_btn.Clicked(f.updateServerInfo)
|
||||
srv_addr_hbox.PackStart(srv_addr_update_btn, false, true, 5)
|
||||
if f.update {
|
||||
f.server_address.SetSensitive(false)
|
||||
}
|
||||
table.Attach(srv_addr_hbox, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5)
|
||||
|
||||
// Server password.
|
||||
srv_pass_label := gtk.NewLabel(ctx.Translator.Translate("Password:", nil))
|
||||
srv_pass_label.SetAlignment(0, 0)
|
||||
table.Attach(srv_pass_label, 0, 1, 2, 3, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
// Server password.
|
||||
srv_pass_label := gtk.NewLabel(ctx.Translator.Translate("Password:", nil))
|
||||
srv_pass_label.SetAlignment(0, 0)
|
||||
table.Attach(srv_pass_label, 0, 1, 2, 3, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
|
||||
f.server_password = gtk.NewEntry()
|
||||
table.Attach(f.server_password, 1, 2, 2, 3, gtk.FILL, gtk.FILL, 5, 5)
|
||||
f.server_password = gtk.NewEntry()
|
||||
table.Attach(f.server_password, 1, 2, 2, 3, gtk.FILL, gtk.FILL, 5, 5)
|
||||
|
||||
// Profile to use.
|
||||
profile_label := gtk.NewLabel(ctx.Translator.Translate("Profile:", nil))
|
||||
profile_label.SetAlignment(0, 0)
|
||||
table.Attach(profile_label, 0, 1, 3, 4, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
// Profile to use.
|
||||
profile_label := gtk.NewLabel(ctx.Translator.Translate("Profile:", nil))
|
||||
profile_label.SetAlignment(0, 0)
|
||||
table.Attach(profile_label, 0, 1, 3, 4, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
|
||||
f.profile = gtk.NewComboBoxText()
|
||||
table.Attach(f.profile , 1, 2, 3, 4, gtk.FILL, gtk.FILL, 5, 5)
|
||||
f.profile = gtk.NewComboBoxText()
|
||||
table.Attach(f.profile, 1, 2, 3, 4, gtk.FILL, gtk.FILL, 5, 5)
|
||||
|
||||
// Invisible thing.
|
||||
inv_label1 := gtk.NewLabel("")
|
||||
table.Attach(inv_label1, 0, 1, 4, 5, gtk.EXPAND, gtk.FILL, 5, 5)
|
||||
inv_label2 := gtk.NewLabel("")
|
||||
table.Attach(inv_label2, 1, 2, 4, 5, gtk.EXPAND, gtk.FILL, 5, 5)
|
||||
// Invisible thing.
|
||||
inv_label1 := gtk.NewLabel("")
|
||||
table.Attach(inv_label1, 0, 1, 4, 5, gtk.EXPAND, gtk.FILL, 5, 5)
|
||||
inv_label2 := gtk.NewLabel("")
|
||||
table.Attach(inv_label2, 1, 2, 4, 5, gtk.EXPAND, gtk.FILL, 5, 5)
|
||||
|
||||
// Buttons hbox.
|
||||
buttons_hbox := gtk.NewHBox(false, 0)
|
||||
sep := gtk.NewHSeparator()
|
||||
buttons_hbox.PackStart(sep, true, true, 5)
|
||||
// OK-Cancel buttons.
|
||||
cancel_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("Cancel", nil))
|
||||
cancel_button.Clicked(f.closeByCancel)
|
||||
buttons_hbox.PackStart(cancel_button, false, true, 5)
|
||||
// Buttons hbox.
|
||||
buttons_hbox := gtk.NewHBox(false, 0)
|
||||
sep := gtk.NewHSeparator()
|
||||
buttons_hbox.PackStart(sep, true, true, 5)
|
||||
// OK-Cancel buttons.
|
||||
cancel_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("Cancel", nil))
|
||||
cancel_button.Clicked(f.closeByCancel)
|
||||
buttons_hbox.PackStart(cancel_button, false, true, 5)
|
||||
|
||||
ok_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("OK", nil))
|
||||
ok_button.Clicked(f.saveFavorite)
|
||||
buttons_hbox.PackStart(ok_button, false, true, 5)
|
||||
ok_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("OK", nil))
|
||||
ok_button.Clicked(f.saveFavorite)
|
||||
buttons_hbox.PackStart(ok_button, false, true, 5)
|
||||
|
||||
f.vbox.PackStart(buttons_hbox, false, true, 5)
|
||||
f.vbox.PackStart(buttons_hbox, false, true, 5)
|
||||
|
||||
f.window.Add(f.vbox)
|
||||
f.window.ShowAll()
|
||||
f.window.Add(f.vbox)
|
||||
f.window.ShowAll()
|
||||
}
|
||||
|
||||
func (f *FavoriteDialog) saveFavorite() error {
|
||||
// Update server's information.
|
||||
f.server.Name = f.server_name.GetText()
|
||||
//ctx.Requester.Pooler.UpdateSpecificServer(f.server)
|
||||
// Update server's information.
|
||||
f.server.Name = f.server_name.GetText()
|
||||
//ctx.Requester.Pooler.UpdateSpecificServer(f.server)
|
||||
|
||||
if len(f.server_address.GetText()) == 0 {
|
||||
// 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("Server address is empty.\n\nServers without address cannot be added.", nil)
|
||||
m := gtk.NewMessageDialog(f.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
return errors.New("No server address specified")
|
||||
}
|
||||
if len(f.server_address.GetText()) == 0 {
|
||||
// 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("Server address is empty.\n\nServers without address cannot be added.", nil)
|
||||
m := gtk.NewMessageDialog(f.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
return errors.New("No server address specified")
|
||||
}
|
||||
|
||||
var port string = ""
|
||||
if strings.Contains(f.server_address.GetText(), ":") {
|
||||
port = strings.Split(f.server_address.GetText(), ":")[1]
|
||||
} else {
|
||||
port = "27960"
|
||||
}
|
||||
f.server.Ip = strings.Split(f.server_address.GetText(), ":")[0]
|
||||
f.server.Port = port
|
||||
var port string = ""
|
||||
if strings.Contains(f.server_address.GetText(), ":") {
|
||||
port = strings.Split(f.server_address.GetText(), ":")[1]
|
||||
} else {
|
||||
port = "27960"
|
||||
}
|
||||
f.server.Ip = strings.Split(f.server_address.GetText(), ":")[0]
|
||||
f.server.Port = port
|
||||
|
||||
if len(f.profile.GetActiveText()) == 0 {
|
||||
// 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("Profile wasn't selected.\n\nPlease, select valid profile for this server.\nIf you haven't add profiles yet - you can do it\nin options on \"Urban Terror\" tab.", nil)
|
||||
m := gtk.NewMessageDialog(f.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
return errors.New("No game profile specified")
|
||||
}
|
||||
if len(f.profile.GetActiveText()) == 0 {
|
||||
// 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("Profile wasn't selected.\n\nPlease, select valid profile for this server.\nIf you haven't add profiles yet - you can do it\nin options on \"Urban Terror\" tab.", nil)
|
||||
m := gtk.NewMessageDialog(f.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
return errors.New("No game profile specified")
|
||||
}
|
||||
|
||||
fmt.Println("Saving favorite server...")
|
||||
fmt.Println(fmt.Sprintf("%+v", f.server))
|
||||
fmt.Println("Saving favorite server...")
|
||||
fmt.Println(fmt.Sprintf("%+v", f.server))
|
||||
|
||||
key := strings.Split(f.server_address.GetText(), ":")[0] + ":" + port
|
||||
key := strings.Split(f.server_address.GetText(), ":")[0] + ":" + port
|
||||
|
||||
// Check if server already in cache. This would replace data about it.
|
||||
_, ok := ctx.Cache.Servers[key]
|
||||
if !ok {
|
||||
ctx.Cache.Servers[key] = &cachemodels.Server{}
|
||||
ctx.Cache.Servers[key].Server = &datamodels.Server{}
|
||||
}
|
||||
// Check if server already in cache. This would replace data about it.
|
||||
_, ok := ctx.Cache.Servers[key]
|
||||
if !ok {
|
||||
ctx.Cache.Servers[key] = &cachemodels.Server{}
|
||||
ctx.Cache.Servers[key].Server = &datamodels.Server{}
|
||||
}
|
||||
|
||||
ctx.Cache.Servers[key].Server.Ip = f.server.Ip
|
||||
ctx.Cache.Servers[key].Server.Port = f.server.Port
|
||||
ctx.Cache.Servers[key].Server.Name = f.server.Name
|
||||
ctx.Cache.Servers[key].Server.Password = f.server_password.GetText()
|
||||
ctx.Cache.Servers[key].Server.ProfileToUse = f.profile.GetActiveText()
|
||||
ctx.Cache.Servers[key].Server.Favorite = "1"
|
||||
ctx.Cache.Servers[key].Server.ExtendedConfig = f.server.ExtendedConfig
|
||||
ctx.Cache.Servers[key].Server.PlayersInfo = f.server.PlayersInfo
|
||||
ctx.Cache.Servers[key].Server.Ip = f.server.Ip
|
||||
ctx.Cache.Servers[key].Server.Port = f.server.Port
|
||||
ctx.Cache.Servers[key].Server.Name = f.server.Name
|
||||
ctx.Cache.Servers[key].Server.Password = f.server_password.GetText()
|
||||
ctx.Cache.Servers[key].Server.ProfileToUse = f.profile.GetActiveText()
|
||||
ctx.Cache.Servers[key].Server.Favorite = "1"
|
||||
ctx.Cache.Servers[key].Server.ExtendedConfig = f.server.ExtendedConfig
|
||||
ctx.Cache.Servers[key].Server.PlayersInfo = f.server.PlayersInfo
|
||||
|
||||
ctx.Eventer.LaunchEvent("flushServers", map[string]string{})
|
||||
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
|
||||
f.window.Destroy()
|
||||
ctx.Eventer.LaunchEvent("flushServers", map[string]string{})
|
||||
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
|
||||
f.window.Destroy()
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FavoriteDialog) updateServerInfo() {
|
||||
fmt.Println("Updating server information...")
|
||||
var port string = ""
|
||||
if strings.Contains(f.server_address.GetText(), ":") {
|
||||
port = strings.Split(f.server_address.GetText(), ":")[1]
|
||||
} else {
|
||||
port = "27960"
|
||||
}
|
||||
f.server.Ip = strings.Split(f.server_address.GetText(), ":")[0]
|
||||
f.server.Port = port
|
||||
fmt.Println("Updating server information...")
|
||||
var port string = ""
|
||||
if strings.Contains(f.server_address.GetText(), ":") {
|
||||
port = strings.Split(f.server_address.GetText(), ":")[1]
|
||||
} else {
|
||||
port = "27960"
|
||||
}
|
||||
f.server.Ip = strings.Split(f.server_address.GetText(), ":")[0]
|
||||
f.server.Port = port
|
||||
|
||||
ctx.Requester.Pooler.UpdateSpecificServer(f.server)
|
||||
ctx.Requester.Pooler.UpdateSpecificServer(f.server)
|
||||
|
||||
f.fill()
|
||||
f.fill()
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,253 +1,253 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
// stdlib
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
// Local
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// Local
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
|
||||
// other
|
||||
"github.com/mattn/go-gtk/glib"
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
// 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()
|
||||
}
|
||||
fmt.Println("Launching Urban Terror...")
|
||||
if len(m.qc_server_address.GetText()) != 0 {
|
||||
m.launchWithQuickConnect()
|
||||
} else {
|
||||
m.launchAsUsual()
|
||||
}
|
||||
|
||||
return nil
|
||||
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 = ""
|
||||
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, ctx.Translator.Translate("Favorites", nil)) {
|
||||
sel = m.fav_servers.GetSelection()
|
||||
model = m.fav_servers.GetModel()
|
||||
}
|
||||
iter := new(gtk.TreeIter)
|
||||
_ = sel.GetSelected(iter)
|
||||
// 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, ctx.Translator.Translate("Favorites", nil)) {
|
||||
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, ctx.Translator.Translate("Servers", nil)) {
|
||||
model.GetValue(iter, m.column_pos["Servers"]["IP"], srv_address_gval)
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
model.GetValue(iter, m.column_pos["Favorites"]["IP"], srv_address_gval)
|
||||
}
|
||||
srv_address = srv_address_gval.GetString()
|
||||
if len(srv_address) == 0 {
|
||||
// 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("No server selected.\n\nPlease, select a server to continue connecting.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
messagebox.Response(func() {
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Select a server we will connect to!", nil) + "</span></markup>"})
|
||||
}
|
||||
return errors.New(ctx.Translator.Translate("No server selected.", nil))
|
||||
}
|
||||
server_profile := ctx.Cache.Servers[srv_address].Server
|
||||
// Getting server address.
|
||||
var srv_addr string
|
||||
srv_address_gval := glib.ValueFromNative(srv_addr)
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
model.GetValue(iter, m.column_pos["Servers"]["IP"], srv_address_gval)
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
model.GetValue(iter, m.column_pos["Favorites"]["IP"], srv_address_gval)
|
||||
}
|
||||
srv_address = srv_address_gval.GetString()
|
||||
if len(srv_address) == 0 {
|
||||
// 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("No server selected.\n\nPlease, select a server to continue connecting.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
messagebox.Response(func() {
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Select a server we will connect to!", nil) + "</span></markup>"})
|
||||
}
|
||||
return errors.New(ctx.Translator.Translate("No server selected.", nil))
|
||||
}
|
||||
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
|
||||
// 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("Selected server is offline.\n\nWould you still want to launch Urban Terror?\nIt will just launch a game, without connecting to\nany server.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO, mbox_string)
|
||||
messagebox.Connect("response", func(resp *glib.CallbackContext) {
|
||||
if resp.Args(0) == 4294967287 {
|
||||
will_continue = false
|
||||
} else {
|
||||
will_continue = true
|
||||
}
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
// We're okay to connect to empty server, temporary.
|
||||
will_continue = true
|
||||
}
|
||||
// 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
|
||||
// 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("Selected server is offline.\n\nWould you still want to launch Urban Terror?\nIt will just launch a game, without connecting to\nany server.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO, mbox_string)
|
||||
messagebox.Connect("response", func(resp *glib.CallbackContext) {
|
||||
if resp.Args(0) == 4294967287 {
|
||||
will_continue = false
|
||||
} else {
|
||||
will_continue = true
|
||||
}
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
// We're okay to connect to empty server, temporary.
|
||||
will_continue = true
|
||||
}
|
||||
|
||||
if !will_continue {
|
||||
return errors.New(ctx.Translator.Translate("User declined to connect to offline server", nil))
|
||||
}
|
||||
}
|
||||
if !will_continue {
|
||||
return errors.New(ctx.Translator.Translate("User declined to connect to offline server", nil))
|
||||
}
|
||||
}
|
||||
|
||||
// Getting selected profile's name.
|
||||
profile_name := m.profiles.GetActiveText()
|
||||
user_profile := &datamodels.Profile{}
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
// 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 {
|
||||
// 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("Invalid game profile selected.\n\nPlease, select profile and retry.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
messagebox.Response(func() {
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Invalid game profile selected.", nil) + "</span></markup>"})
|
||||
}
|
||||
return errors.New(ctx.Translator.Translate("User didn't select valid profile.", nil))
|
||||
}
|
||||
user_profile = ctx.Cache.Profiles[profile_name].Profile
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
// For favorite servers profile specified in favorite server
|
||||
// information have higher priority, so we just override it :)
|
||||
user_profile_cached, ok := ctx.Cache.Profiles[server_profile.ProfileToUse]
|
||||
if !ok {
|
||||
// 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("Invalid game profile specified for favorite server.\n\nPlease, edit your favorite server, select valid profile and retry.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
messagebox.Response(func() {
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Invalid game profile specified in favorite entry.", nil) + "</span></markup>"})
|
||||
}
|
||||
return errors.New(ctx.Translator.Translate("User didn't select valid profile.", nil))
|
||||
}
|
||||
user_profile = user_profile_cached.Profile
|
||||
}
|
||||
// Getting selected profile's name.
|
||||
profile_name := m.profiles.GetActiveText()
|
||||
user_profile := &datamodels.Profile{}
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
// 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 {
|
||||
// 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("Invalid game profile selected.\n\nPlease, select profile and retry.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
messagebox.Response(func() {
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Invalid game profile selected.", nil) + "</span></markup>"})
|
||||
}
|
||||
return errors.New(ctx.Translator.Translate("User didn't select valid profile.", nil))
|
||||
}
|
||||
user_profile = ctx.Cache.Profiles[profile_name].Profile
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
// For favorite servers profile specified in favorite server
|
||||
// information have higher priority, so we just override it :)
|
||||
user_profile_cached, ok := ctx.Cache.Profiles[server_profile.ProfileToUse]
|
||||
if !ok {
|
||||
// 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("Invalid game profile specified for favorite server.\n\nPlease, edit your favorite server, select valid profile and retry.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
messagebox.Response(func() {
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Invalid game profile specified in favorite entry.", nil) + "</span></markup>"})
|
||||
}
|
||||
return errors.New(ctx.Translator.Translate("User didn't select valid profile.", nil))
|
||||
}
|
||||
user_profile = user_profile_cached.Profile
|
||||
}
|
||||
|
||||
m.launchActually(server_profile, user_profile, "", "")
|
||||
return nil
|
||||
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...")
|
||||
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()
|
||||
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"
|
||||
}
|
||||
// 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
|
||||
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)
|
||||
}
|
||||
_, 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]
|
||||
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
|
||||
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
|
||||
// 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("Selected server is offline.\n\nWould you still want to launch Urban Terror?\nIt will just launch a game, without connecting to\nany server.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO, mbox_string)
|
||||
messagebox.Connect("response", func(resp *glib.CallbackContext) {
|
||||
if resp.Args(0) == 4294967287 {
|
||||
will_continue = false
|
||||
} else {
|
||||
will_continue = true
|
||||
}
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
// We're ok here, temporary.
|
||||
will_continue = true
|
||||
}
|
||||
if server_profile.Name == "" {
|
||||
var will_continue bool = false
|
||||
// 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("Selected server is offline.\n\nWould you still want to launch Urban Terror?\nIt will just launch a game, without connecting to\nany server.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO, mbox_string)
|
||||
messagebox.Connect("response", func(resp *glib.CallbackContext) {
|
||||
if resp.Args(0) == 4294967287 {
|
||||
will_continue = false
|
||||
} else {
|
||||
will_continue = true
|
||||
}
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
// We're ok here, temporary.
|
||||
will_continue = true
|
||||
}
|
||||
|
||||
if !will_continue {
|
||||
return errors.New(ctx.Translator.Translate("User declined to connect to offline server", nil))
|
||||
}
|
||||
}
|
||||
if !will_continue {
|
||||
return errors.New(ctx.Translator.Translate("User declined to connect to offline server", nil))
|
||||
}
|
||||
}
|
||||
|
||||
// Check if server is applicable for selected profile.
|
||||
if server_profile.Version != user_profile.Version {
|
||||
// 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("Invalid game profile selected.\n\nSelected profile have different game version than server.\nPlease, select valid profile and retry.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
messagebox.Response(func() {
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Invalid game profile selected.", nil) + "</span></markup>"})
|
||||
}
|
||||
return errors.New(ctx.Translator.Translate("User didn't select valid profile, mismatch with server's version.", nil))
|
||||
}
|
||||
// Check if server is applicable for selected profile.
|
||||
if server_profile.Version != user_profile.Version {
|
||||
// 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("Invalid game profile selected.\n\nSelected profile have different game version than server.\nPlease, select valid profile and retry.", nil)
|
||||
messagebox := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
messagebox.Response(func() {
|
||||
messagebox.Destroy()
|
||||
})
|
||||
messagebox.Run()
|
||||
} else {
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Invalid game profile selected.", nil) + "</span></markup>"})
|
||||
}
|
||||
return errors.New(ctx.Translator.Translate("User didn't select valid profile, mismatch with server's version.", nil))
|
||||
}
|
||||
|
||||
server_password := password
|
||||
if len(server_password) == 0 {
|
||||
server_password = server_profile.Password
|
||||
}
|
||||
server_password := password
|
||||
if len(server_password) == 0 {
|
||||
server_password = server_profile.Password
|
||||
}
|
||||
|
||||
// Hey, we're ok here! :) Launch Urban Terror!
|
||||
// Clear server name from "<markup></markup>" things.
|
||||
srv_name_for_label := server_profile.Name
|
||||
if strings.Contains(server_profile.Name, "markup") {
|
||||
srv_name_for_label = string([]byte(server_profile.Name)[8:len(server_profile.Name)-9])
|
||||
} else {
|
||||
srv_name := ctx.Colorizer.Fix(server_profile.Name)
|
||||
srv_name_for_label = string([]byte(srv_name)[8:len(srv_name)-9])
|
||||
}
|
||||
// Show great coloured label.
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Urban Terror is launched with profile", nil) + " </span><span foreground=\"blue\">" + user_profile.Name + "</span> <span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("and connected to", nil) + " </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)
|
||||
// Hey, we're ok here! :) Launch Urban Terror!
|
||||
// Clear server name from "<markup></markup>" things.
|
||||
srv_name_for_label := server_profile.Name
|
||||
if strings.Contains(server_profile.Name, "markup") {
|
||||
srv_name_for_label = string([]byte(server_profile.Name)[8 : len(server_profile.Name)-9])
|
||||
} else {
|
||||
srv_name := ctx.Colorizer.Fix(server_profile.Name)
|
||||
srv_name_for_label = string([]byte(srv_name)[8 : len(srv_name)-9])
|
||||
}
|
||||
// Show great coloured label.
|
||||
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Urban Terror is launched with profile", nil) + " </span><span foreground=\"blue\">" + user_profile.Name + "</span> <span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("and connected to", nil) + " </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
|
||||
return nil
|
||||
}
|
||||
|
@ -1,96 +1,96 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"strconv"
|
||||
"strings"
|
||||
// stdlib
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
// other
|
||||
"github.com/mattn/go-gtk/glib"
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
// other
|
||||
"github.com/mattn/go-gtk/glib"
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
)
|
||||
|
||||
func (m *MainWindow) sortServersByName(model *gtk.TreeModel, a *gtk.TreeIter, b *gtk.TreeIter) int {
|
||||
var name1_raw glib.GValue
|
||||
var name2_raw glib.GValue
|
||||
func (m *MainWindow) sortServersByName(model *gtk.TreeModel, a *gtk.TreeIter, b *gtk.TreeIter, userData interface{}) int {
|
||||
var name1_raw glib.GValue
|
||||
var name2_raw glib.GValue
|
||||
|
||||
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
model.GetValue(a, m.column_pos["Servers"][ctx.Translator.Translate("Name", nil)], &name1_raw)
|
||||
model.GetValue(b, m.column_pos["Servers"][ctx.Translator.Translate("Name", nil)], &name2_raw)
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
model.GetValue(a, m.column_pos["Favorites"][ctx.Translator.Translate("Name", nil)], &name1_raw)
|
||||
model.GetValue(b, m.column_pos["Favorites"][ctx.Translator.Translate("Name", nil)], &name2_raw)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
model.GetValue(a, m.column_pos["Servers"][ctx.Translator.Translate("Name", nil)], &name1_raw)
|
||||
model.GetValue(b, m.column_pos["Servers"][ctx.Translator.Translate("Name", nil)], &name2_raw)
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
model.GetValue(a, m.column_pos["Favorites"][ctx.Translator.Translate("Name", nil)], &name1_raw)
|
||||
model.GetValue(b, m.column_pos["Favorites"][ctx.Translator.Translate("Name", nil)], &name2_raw)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
|
||||
name1 := strings.ToLower(ctx.Colorizer.ClearFromMarkup(name1_raw.GetString()))
|
||||
name2 := strings.ToLower(ctx.Colorizer.ClearFromMarkup(name2_raw.GetString()))
|
||||
name1 := strings.ToLower(ctx.Colorizer.ClearFromMarkup(name1_raw.GetString()))
|
||||
name2 := strings.ToLower(ctx.Colorizer.ClearFromMarkup(name2_raw.GetString()))
|
||||
|
||||
if name1 < name2 {
|
||||
return -1
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
if name1 < name2 {
|
||||
return -1
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *MainWindow) sortServersByPlayers(model *gtk.TreeModel, a *gtk.TreeIter, b *gtk.TreeIter) int {
|
||||
var players1_raw glib.GValue
|
||||
var players2_raw glib.GValue
|
||||
func (m *MainWindow) sortServersByPlayers(model *gtk.TreeModel, a *gtk.TreeIter, b *gtk.TreeIter, userData interface{}) int {
|
||||
var players1_raw glib.GValue
|
||||
var players2_raw glib.GValue
|
||||
|
||||
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
model.GetValue(a, m.column_pos["Servers"][ctx.Translator.Translate("Players", nil)], &players1_raw)
|
||||
model.GetValue(b, m.column_pos["Servers"][ctx.Translator.Translate("Players", nil)], &players2_raw)
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
model.GetValue(a, m.column_pos["Favorites"][ctx.Translator.Translate("Players", nil)], &players1_raw)
|
||||
model.GetValue(b, m.column_pos["Favorites"][ctx.Translator.Translate("Players", nil)], &players2_raw)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
model.GetValue(a, m.column_pos["Servers"][ctx.Translator.Translate("Players", nil)], &players1_raw)
|
||||
model.GetValue(b, m.column_pos["Servers"][ctx.Translator.Translate("Players", nil)], &players2_raw)
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
model.GetValue(a, m.column_pos["Favorites"][ctx.Translator.Translate("Players", nil)], &players1_raw)
|
||||
model.GetValue(b, m.column_pos["Favorites"][ctx.Translator.Translate("Players", nil)], &players2_raw)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
|
||||
players1_online := strings.Split(players1_raw.GetString(), "/")[0]
|
||||
players2_online := strings.Split(players2_raw.GetString(), "/")[0]
|
||||
players1_online := strings.Split(players1_raw.GetString(), "/")[0]
|
||||
players2_online := strings.Split(players2_raw.GetString(), "/")[0]
|
||||
|
||||
if len(players1_online) > 0 && len(players2_online) > 0 {
|
||||
players1, _ := strconv.Atoi(players1_online)
|
||||
players2, _ := strconv.Atoi(players2_online)
|
||||
if players1 > players2 {
|
||||
return -1
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if len(players1_online) > 0 && len(players2_online) > 0 {
|
||||
players1, _ := strconv.Atoi(players1_online)
|
||||
players2, _ := strconv.Atoi(players2_online)
|
||||
if players1 > players2 {
|
||||
return -1
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
return -1
|
||||
}
|
||||
|
||||
func (m *MainWindow) sortServersByPing(model *gtk.TreeModel, a *gtk.TreeIter, b *gtk.TreeIter) int {
|
||||
var ping1_raw glib.GValue
|
||||
var ping2_raw glib.GValue
|
||||
func (m *MainWindow) sortServersByPing(model *gtk.TreeModel, a *gtk.TreeIter, b *gtk.TreeIter, userData interface{}) int {
|
||||
var ping1_raw glib.GValue
|
||||
var ping2_raw glib.GValue
|
||||
|
||||
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
model.GetValue(a, m.column_pos["Servers"][ctx.Translator.Translate("Ping", nil)], &ping1_raw)
|
||||
model.GetValue(b, m.column_pos["Servers"][ctx.Translator.Translate("Ping", nil)], &ping2_raw)
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
model.GetValue(a, m.column_pos["Favorites"][ctx.Translator.Translate("Ping", nil)], &ping1_raw)
|
||||
model.GetValue(b, m.column_pos["Favorites"][ctx.Translator.Translate("Ping", nil)], &ping2_raw)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
|
||||
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
|
||||
model.GetValue(a, m.column_pos["Servers"][ctx.Translator.Translate("Ping", nil)], &ping1_raw)
|
||||
model.GetValue(b, m.column_pos["Servers"][ctx.Translator.Translate("Ping", nil)], &ping2_raw)
|
||||
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
|
||||
model.GetValue(a, m.column_pos["Favorites"][ctx.Translator.Translate("Ping", nil)], &ping1_raw)
|
||||
model.GetValue(b, m.column_pos["Favorites"][ctx.Translator.Translate("Ping", nil)], &ping2_raw)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
|
||||
ping1, _ := strconv.Atoi(ping1_raw.GetString())
|
||||
ping2, _ := strconv.Atoi(ping2_raw.GetString())
|
||||
ping1, _ := strconv.Atoi(ping1_raw.GetString())
|
||||
ping2, _ := strconv.Atoi(ping2_raw.GetString())
|
||||
|
||||
if ping1 < ping2 {
|
||||
return 1
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
if ping1 < ping2 {
|
||||
return 1
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
|
||||
return -1
|
||||
return -1
|
||||
}
|
||||
|
@ -10,427 +10,427 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
"runtime"
|
||||
// stdlib
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
// Local
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// Local
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
"github.com/mattn/go-gtk/glib"
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/glib"
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
)
|
||||
|
||||
type OptionsDialog struct {
|
||||
// Window.
|
||||
window *gtk.Window
|
||||
// Options main VBox.
|
||||
vbox *gtk.VBox
|
||||
// Tabs widget.
|
||||
tab_widget *gtk.Notebook
|
||||
// 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
|
||||
// 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
|
||||
// Data stores.
|
||||
// Urban Terror profiles list.
|
||||
profiles_list_store *gtk.ListStore
|
||||
}
|
||||
|
||||
func (o *OptionsDialog) addProfile() {
|
||||
fmt.Println("Adding profile...")
|
||||
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{})
|
||||
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()
|
||||
o.window.Destroy()
|
||||
}
|
||||
|
||||
func (o *OptionsDialog) closeOptionsDialogWithDiscard() {
|
||||
}
|
||||
|
||||
func (o *OptionsDialog) closeOptionsDialogWithSaving() {
|
||||
fmt.Println("Saving changes to options...")
|
||||
fmt.Println("Saving changes to options...")
|
||||
|
||||
o.saveGeneral()
|
||||
o.saveAppearance()
|
||||
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()
|
||||
}
|
||||
// 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()
|
||||
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()
|
||||
// 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 + "'")
|
||||
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{})
|
||||
}
|
||||
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()
|
||||
// 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{})
|
||||
}
|
||||
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)
|
||||
}
|
||||
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 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_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)
|
||||
}
|
||||
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_vbox := gtk.NewVBox(false, 0)
|
||||
|
||||
appearance_table := gtk.NewTable(1, 2, false)
|
||||
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_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)
|
||||
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)
|
||||
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.EXPAND, 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)
|
||||
o.tab_widget.AppendPage(appearance_vbox, gtk.NewLabel(ctx.Translator.Translate("Appearance", nil)))
|
||||
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_vbox := gtk.NewVBox(false, 0)
|
||||
|
||||
general_table := gtk.NewTable(2, 2, false)
|
||||
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)
|
||||
// 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.EXPAND, gtk.FILL, 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.EXPAND, 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)
|
||||
// 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.EXPAND, gtk.FILL, 5, 5)
|
||||
o.autoupdate = gtk.NewCheckButtonWithLabel("")
|
||||
o.autoupdate.SetTooltipText(autoupdate_tooltip)
|
||||
general_table.Attach(o.autoupdate, 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL, 5, 5)
|
||||
|
||||
// Vertical separator.
|
||||
sep := gtk.NewVBox(false, 0)
|
||||
// Vertical separator.
|
||||
sep := gtk.NewVBox(false, 0)
|
||||
|
||||
general_vbox.PackStart(general_table, false, true, 0)
|
||||
general_vbox.PackStart(sep, false, true, 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)))
|
||||
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_options_vbox := gtk.NewVBox(false, 0)
|
||||
|
||||
servers_updating_table := gtk.NewTable(3, 2, false)
|
||||
servers_updating_table.SetRowSpacings(2)
|
||||
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)
|
||||
// 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)
|
||||
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)
|
||||
// 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.EXPAND | gtk.FILL, gtk.FILL, 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.EXPAND|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)
|
||||
// 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)
|
||||
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)
|
||||
// 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)
|
||||
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)))
|
||||
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)
|
||||
// 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.initializeStorages()
|
||||
o.tab_widget = gtk.NewNotebook()
|
||||
o.tab_widget.SetTabPos(gtk.POS_LEFT)
|
||||
|
||||
o.initializeGeneralTab()
|
||||
o.initializeAppearanceTab()
|
||||
o.initializeUrtTab()
|
||||
o.initializeServersOptionsTab()
|
||||
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)
|
||||
// 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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
o.vbox.PackStart(o.tab_widget, true, true, 5)
|
||||
o.vbox.PackStart(buttons_hbox, false, true, 5)
|
||||
|
||||
ctx.Eventer.AddEventHandler("loadProfilesIntoOptionsWindow", o.loadProfiles)
|
||||
ctx.Eventer.AddEventHandler("loadProfilesIntoOptionsWindow", o.loadProfiles)
|
||||
}
|
||||
|
||||
func (o *OptionsDialog) initializeUrtTab() {
|
||||
urt_hbox := gtk.NewHBox(false, 5)
|
||||
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.
|
||||
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)
|
||||
// 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_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)
|
||||
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)
|
||||
// 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)
|
||||
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)
|
||||
urt_hbox.Add(urt_profiles_buttons_vbox)
|
||||
|
||||
o.tab_widget.AppendPage(urt_hbox, gtk.NewLabel(ctx.Translator.Translate("Urban Terror", nil)))
|
||||
o.tab_widget.AppendPage(urt_hbox, gtk.NewLabel(ctx.Translator.Translate("Urban Terror", nil)))
|
||||
|
||||
// Load Profiles.
|
||||
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
||||
// 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()
|
||||
fmt.Println("Loading profiles...")
|
||||
o.profiles_list_store.Clear()
|
||||
|
||||
ctx.Cache.ProfilesMutex.Lock()
|
||||
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)
|
||||
}
|
||||
ctx.Cache.ProfilesMutex.Unlock()
|
||||
ctx.Cache.ProfilesMutex.Lock()
|
||||
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)
|
||||
}
|
||||
ctx.Cache.ProfilesMutex.Unlock()
|
||||
}
|
||||
|
||||
func (o *OptionsDialog) saveAppearance() {
|
||||
ctx.Cfg.Cfg["/general/language"] = ctx.Translator.AcceptedLanguages[o.language_combo.GetActiveText()]
|
||||
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.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"
|
||||
}
|
||||
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
|
||||
}
|
||||
// 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"
|
||||
}
|
||||
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
|
||||
}
|
||||
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{})
|
||||
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(750, 600)
|
||||
o.window.SetPosition(gtk.WIN_POS_CENTER)
|
||||
o.window.SetIcon(logo)
|
||||
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(750, 600)
|
||||
o.window.SetPosition(gtk.WIN_POS_CENTER)
|
||||
o.window.SetIcon(logo)
|
||||
|
||||
o.vbox = gtk.NewVBox(false, 0)
|
||||
o.vbox = gtk.NewVBox(false, 0)
|
||||
|
||||
o.initializeTabs()
|
||||
o.fill()
|
||||
o.initializeTabs()
|
||||
o.fill()
|
||||
|
||||
o.window.Add(o.vbox)
|
||||
o.window.Add(o.vbox)
|
||||
|
||||
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
||||
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
||||
|
||||
o.window.ShowAll()
|
||||
o.window.ShowAll()
|
||||
}
|
||||
|
@ -10,391 +10,390 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
// stdlib
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
// Local
|
||||
"github.com/pztrn/urtrator/datamodels"
|
||||
// Local
|
||||
"gitlab.com/pztrn/urtrator/datamodels"
|
||||
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
//"github.com/mattn/go-gtk/glib"
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
//"github.com/mattn/go-gtk/glib"
|
||||
)
|
||||
|
||||
type OptionsProfile struct {
|
||||
// Window.
|
||||
window *gtk.Window
|
||||
// Main table.
|
||||
table *gtk.Table
|
||||
// Profile name.
|
||||
profile_name *gtk.Entry
|
||||
// Binary path.
|
||||
binary_path *gtk.Entry
|
||||
// Profile directory path.
|
||||
profile_path *gtk.Entry
|
||||
// Urban Terror versions combobox
|
||||
urt_version_combo *gtk.ComboBoxText
|
||||
// Another X session?
|
||||
another_x_session *gtk.CheckButton
|
||||
// Additional parameters for game launching.
|
||||
additional_parameters *gtk.Entry
|
||||
// Window.
|
||||
window *gtk.Window
|
||||
// Main table.
|
||||
table *gtk.Table
|
||||
// Profile name.
|
||||
profile_name *gtk.Entry
|
||||
// Binary path.
|
||||
binary_path *gtk.Entry
|
||||
// Profile directory path.
|
||||
profile_path *gtk.Entry
|
||||
// Urban Terror versions combobox
|
||||
urt_version_combo *gtk.ComboBoxText
|
||||
// Another X session?
|
||||
another_x_session *gtk.CheckButton
|
||||
// Additional parameters for game launching.
|
||||
additional_parameters *gtk.Entry
|
||||
|
||||
// File chooser dialog for selecting binary.
|
||||
f *gtk.FileChooserDialog
|
||||
// Profile directory chooser dialog.
|
||||
p *gtk.FileChooserDialog
|
||||
// File chooser dialog for selecting binary.
|
||||
f *gtk.FileChooserDialog
|
||||
// Profile directory chooser dialog.
|
||||
p *gtk.FileChooserDialog
|
||||
|
||||
// Flags.
|
||||
// This is profile update?
|
||||
update bool
|
||||
// Flags.
|
||||
// This is profile update?
|
||||
update bool
|
||||
|
||||
// Others.
|
||||
// Old profile, needed for proper update.
|
||||
old_profile *datamodels.Profile
|
||||
// Others.
|
||||
// Old profile, needed for proper update.
|
||||
old_profile *datamodels.Profile
|
||||
}
|
||||
|
||||
func (op *OptionsProfile) browseForBinary() {
|
||||
op.f = gtk.NewFileChooserDialog(ctx.Translator.Translate("URTrator - Select Urban Terror binary", nil), op.window, gtk.FILE_CHOOSER_ACTION_OPEN, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
|
||||
op.f.Response(op.browseForBinaryHelper)
|
||||
op.f.Run()
|
||||
op.f = gtk.NewFileChooserDialog(ctx.Translator.Translate("URTrator - Select Urban Terror binary", nil), op.window, gtk.FILE_CHOOSER_ACTION_OPEN, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
|
||||
op.f.Response(op.browseForBinaryHelper)
|
||||
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()
|
||||
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() {
|
||||
filename := op.f.GetFilename()
|
||||
op.binary_path.SetText(filename)
|
||||
op.f.Destroy()
|
||||
fmt.Println(filename)
|
||||
filename := op.f.GetFilename()
|
||||
op.binary_path.SetText(filename)
|
||||
op.f.Destroy()
|
||||
fmt.Println(filename)
|
||||
|
||||
// Check for valid filename.
|
||||
// ToDo: add more OSes.
|
||||
if runtime.GOOS == "linux" {
|
||||
// Filename should end with approriate arch.
|
||||
if runtime.GOARCH == "amd64" {
|
||||
if len(filename) > 0 && strings.Split(filename, ".")[1] != "x86_64" && strings.Split(filename, ".")[0] != "Quake3-UrT" {
|
||||
fmt.Println("Invalid binary selected!")
|
||||
// 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("Invalid binary selected!\nAccording to your OS, it should be", nil) + " Quake3-UrT.x86_64."
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
//
|
||||
}
|
||||
op.binary_path.SetText("")
|
||||
}
|
||||
}
|
||||
} else if runtime.GOOS == "darwin" {
|
||||
// Official application: Quake3-UrT.app. Split by it and get second
|
||||
// part of string.
|
||||
if strings.Contains(filename, "Quake3-UrT.app") {
|
||||
filename = strings.Split(filename, "Quake3-UrT.app")[1]
|
||||
if len(filename) > 0 && !strings.Contains(strings.Split(filename, ".")[1], "x86_64") && !strings.Contains(strings.Split(filename, ".")[0], "Quake3-UrT") {
|
||||
fmt.Println("Invalid binary selected!")
|
||||
// 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("Invalid binary selected!\nAccording to your OS, it should be", nil) + " Quake3-UrT.app/Contents/MacOS/Quake3-UrT.x86_64."
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
//
|
||||
}
|
||||
op.binary_path.SetText("")
|
||||
}
|
||||
} else {
|
||||
// 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("Invalid binary selected!\nAccording to your OS, it should be", nil) + " Quake3-UrT.app/Contents/MacOS/Quake3-UrT.x86_64.\n\n" + ctx.Translator.Translate("Note, that currently URTrator supports only official binary.", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for valid filename.
|
||||
// ToDo: add more OSes.
|
||||
if runtime.GOOS == "linux" {
|
||||
// Filename should end with approriate arch.
|
||||
if runtime.GOARCH == "amd64" {
|
||||
if len(filename) > 0 && strings.Split(filename, ".")[1] != "x86_64" && strings.Split(filename, ".")[0] != "Quake3-UrT" {
|
||||
fmt.Println("Invalid binary selected!")
|
||||
// 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("Invalid binary selected!\nAccording to your OS, it should be", nil) + " Quake3-UrT.x86_64."
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
//
|
||||
}
|
||||
op.binary_path.SetText("")
|
||||
}
|
||||
}
|
||||
} else if runtime.GOOS == "darwin" {
|
||||
// Official application: Quake3-UrT.app. Split by it and get second
|
||||
// part of string.
|
||||
if strings.Contains(filename, "Quake3-UrT.app") {
|
||||
filename = strings.Split(filename, "Quake3-UrT.app")[1]
|
||||
if len(filename) > 0 && !strings.Contains(strings.Split(filename, ".")[1], "x86_64") && !strings.Contains(strings.Split(filename, ".")[0], "Quake3-UrT") {
|
||||
fmt.Println("Invalid binary selected!")
|
||||
// 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("Invalid binary selected!\nAccording to your OS, it should be", nil) + " Quake3-UrT.app/Contents/MacOS/Quake3-UrT.x86_64."
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
//
|
||||
}
|
||||
op.binary_path.SetText("")
|
||||
}
|
||||
} else {
|
||||
// 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("Invalid binary selected!\nAccording to your OS, it should be", nil) + " Quake3-UrT.app/Contents/MacOS/Quake3-UrT.x86_64.\n\n" + ctx.Translator.Translate("Note, that currently URTrator supports only official binary.", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if op.profile_path.GetText() == "" {
|
||||
op.profile_path.SetText(ctx.Cfg.TEMP["DEFAULT_PROFILE_PATH"])
|
||||
}
|
||||
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()
|
||||
directory := op.p.GetFilename()
|
||||
op.profile_path.SetText(directory)
|
||||
op.p.Destroy()
|
||||
}
|
||||
|
||||
func (op *OptionsProfile) closeByCancel() {
|
||||
op.window.Destroy()
|
||||
op.window.Destroy()
|
||||
}
|
||||
|
||||
func (op *OptionsProfile) closeWithDiscard() {
|
||||
}
|
||||
|
||||
func (op *OptionsProfile) Initialize(update bool) {
|
||||
if update {
|
||||
op.update = true
|
||||
}
|
||||
if update {
|
||||
op.update = true
|
||||
}
|
||||
|
||||
op.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
|
||||
if update {
|
||||
op.window.SetTitle(ctx.Translator.Translate("URTrator - Update Urban Terror profile", nil))
|
||||
} else {
|
||||
op.window.SetTitle(ctx.Translator.Translate("URTrator - Add Urban Terror profile", nil))
|
||||
}
|
||||
op.window.Connect("destroy", op.closeWithDiscard)
|
||||
op.window.SetModal(true)
|
||||
op.window.SetSizeRequest(550, 400)
|
||||
op.window.SetPosition(gtk.WIN_POS_CENTER)
|
||||
op.window.SetIcon(logo)
|
||||
op.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
|
||||
if update {
|
||||
op.window.SetTitle(ctx.Translator.Translate("URTrator - Update Urban Terror profile", nil))
|
||||
} else {
|
||||
op.window.SetTitle(ctx.Translator.Translate("URTrator - Add Urban Terror profile", nil))
|
||||
}
|
||||
op.window.Connect("destroy", op.closeWithDiscard)
|
||||
op.window.SetModal(true)
|
||||
op.window.SetSizeRequest(550, 400)
|
||||
op.window.SetPosition(gtk.WIN_POS_CENTER)
|
||||
op.window.SetIcon(logo)
|
||||
|
||||
op.table = gtk.NewTable(7, 2, false)
|
||||
op.table.SetRowSpacings(2)
|
||||
op.table = gtk.NewTable(7, 2, false)
|
||||
op.table.SetRowSpacings(2)
|
||||
|
||||
// Profile name.
|
||||
profile_name_tooltip := ctx.Translator.Translate("This how you will see profile on profiles lists.", nil)
|
||||
pn_label := gtk.NewLabel(ctx.Translator.Translate("Profile name:", nil))
|
||||
pn_label.SetTooltipText(profile_name_tooltip)
|
||||
pn_label.SetAlignment(0, 0)
|
||||
op.table.Attach(pn_label, 0, 1, 0, 1, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
// Profile name.
|
||||
profile_name_tooltip := ctx.Translator.Translate("This how you will see profile on profiles lists.", nil)
|
||||
pn_label := gtk.NewLabel(ctx.Translator.Translate("Profile name:", nil))
|
||||
pn_label.SetTooltipText(profile_name_tooltip)
|
||||
pn_label.SetAlignment(0, 0)
|
||||
op.table.Attach(pn_label, 0, 1, 0, 1, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
|
||||
op.profile_name = gtk.NewEntry()
|
||||
op.profile_name.SetTooltipText(profile_name_tooltip)
|
||||
op.table.Attach(op.profile_name, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
|
||||
op.profile_name = gtk.NewEntry()
|
||||
op.profile_name.SetTooltipText(profile_name_tooltip)
|
||||
op.table.Attach(op.profile_name, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
|
||||
|
||||
// Urban Terror version.
|
||||
urt_version_tooltip := ctx.Translator.Translate("Urban Terror version for which this profile applies.", nil)
|
||||
urt_version_label := gtk.NewLabel(ctx.Translator.Translate("Urban Terror version:", nil))
|
||||
urt_version_label.SetTooltipText(urt_version_tooltip)
|
||||
urt_version_label.SetAlignment(0, 0)
|
||||
op.table.Attach(urt_version_label, 0, 1, 1, 2, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
|
||||
// Urban Terror version.
|
||||
urt_version_tooltip := ctx.Translator.Translate("Urban Terror version for which this profile applies.", nil)
|
||||
urt_version_label := gtk.NewLabel(ctx.Translator.Translate("Urban Terror version:", nil))
|
||||
urt_version_label.SetTooltipText(urt_version_tooltip)
|
||||
urt_version_label.SetAlignment(0, 0)
|
||||
op.table.Attach(urt_version_label, 0, 1, 1, 2, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
op.urt_version_combo = gtk.NewComboBoxText()
|
||||
op.urt_version_combo.SetTooltipText(urt_version_tooltip)
|
||||
op.urt_version_combo.AppendText("4.2.023")
|
||||
op.urt_version_combo.AppendText("4.3.1")
|
||||
op.urt_version_combo.AppendText("4.3.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.urt_version_combo = gtk.NewComboBoxText()
|
||||
op.urt_version_combo.SetTooltipText(urt_version_tooltip)
|
||||
op.urt_version_combo.AppendText("4.2.023")
|
||||
op.urt_version_combo.AppendText("4.3.1")
|
||||
op.urt_version_combo.AppendText("4.3.2")
|
||||
op.urt_version_combo.SetActive(2)
|
||||
op.table.Attach(op.urt_version_combo, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5)
|
||||
// Urban Terror binary path.
|
||||
select_binary_tooltip := ctx.Translator.Translate("Urban Terror binary. Some checks will be executed, so make sure you have selected right binary:\n\nQuake3-UrT.i386 for linux-x86\nQuake3-UrT.x86_64 for linux-amd64\nQuake3-UrT.app for macOS", nil)
|
||||
binpath_hbox := gtk.NewHBox(false, 0)
|
||||
binpath_label := gtk.NewLabel(ctx.Translator.Translate("Urban Terror binary:", nil))
|
||||
binpath_label.SetTooltipText(select_binary_tooltip)
|
||||
binpath_label.SetAlignment(0, 0)
|
||||
op.table.Attach(binpath_label, 0, 1, 2, 3, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
|
||||
// Urban Terror binary path.
|
||||
select_binary_tooltip := ctx.Translator.Translate("Urban Terror binary. Some checks will be executed, so make sure you have selected right binary:\n\nQuake3-UrT.i386 for linux-x86\nQuake3-UrT.x86_64 for linux-amd64\nQuake3-UrT.app for macOS", nil)
|
||||
binpath_hbox := gtk.NewHBox(false, 0)
|
||||
binpath_label := gtk.NewLabel(ctx.Translator.Translate("Urban Terror binary:", nil))
|
||||
binpath_label.SetTooltipText(select_binary_tooltip)
|
||||
binpath_label.SetAlignment(0, 0)
|
||||
op.table.Attach(binpath_label, 0, 1, 2, 3, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
op.binary_path = gtk.NewEntry()
|
||||
op.binary_path.SetTooltipText(select_binary_tooltip)
|
||||
button_select_binary := gtk.NewButtonWithLabel(ctx.Translator.Translate("Browse", nil))
|
||||
button_select_binary.SetTooltipText(select_binary_tooltip)
|
||||
button_select_binary.Clicked(op.browseForBinary)
|
||||
binpath_hbox.PackStart(op.binary_path, true, 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.binary_path = gtk.NewEntry()
|
||||
op.binary_path.SetTooltipText(select_binary_tooltip)
|
||||
button_select_binary := gtk.NewButtonWithLabel(ctx.Translator.Translate("Browse", nil))
|
||||
button_select_binary.SetTooltipText(select_binary_tooltip)
|
||||
button_select_binary.Clicked(op.browseForBinary)
|
||||
binpath_hbox.PackStart(op.binary_path, true, 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)
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
|
||||
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?
|
||||
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.SetTooltipText(another_x_tooltip)
|
||||
another_x_label.SetAlignment(0, 0)
|
||||
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.SetTooltipText(another_x_tooltip)
|
||||
// macOS and Windows can't do that :).
|
||||
if runtime.GOOS != "linux" {
|
||||
op.another_x_session.SetSensitive(false)
|
||||
}
|
||||
op.table.Attach(op.another_x_session, 1, 2, 4, 5, gtk.FILL, gtk.FILL, 5, 5)
|
||||
|
||||
// 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_label := gtk.NewLabel(ctx.Translator.Translate("Start Urban Terror in another X session?", nil))
|
||||
another_x_label.SetTooltipText(another_x_tooltip)
|
||||
another_x_label.SetAlignment(0, 0)
|
||||
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.SetTooltipText(another_x_tooltip)
|
||||
// macOS and Windows can't do that :).
|
||||
if runtime.GOOS != "linux" {
|
||||
op.another_x_session.SetSensitive(false)
|
||||
}
|
||||
op.table.Attach(op.another_x_session, 1, 2, 4, 5, gtk.FILL, gtk.FILL, 5, 5)
|
||||
// Additional game parameters.
|
||||
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.SetTooltipText(params_tooltip)
|
||||
params_label.SetAlignment(0, 0)
|
||||
op.table.Attach(params_label, 0, 1, 5, 6, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
|
||||
// Additional game parameters.
|
||||
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.SetTooltipText(params_tooltip)
|
||||
params_label.SetAlignment(0, 0)
|
||||
op.table.Attach(params_label, 0, 1, 5, 6, gtk.FILL, gtk.SHRINK, 5, 5)
|
||||
op.additional_parameters = gtk.NewEntry()
|
||||
op.additional_parameters.SetTooltipText(params_tooltip)
|
||||
op.table.Attach(op.additional_parameters, 1, 2, 5, 6, gtk.FILL, gtk.FILL, 5, 5)
|
||||
|
||||
op.additional_parameters = gtk.NewEntry()
|
||||
op.additional_parameters.SetTooltipText(params_tooltip)
|
||||
op.table.Attach(op.additional_parameters, 1, 2, 5, 6, gtk.FILL, gtk.FILL, 5, 5)
|
||||
// Invisible thing.
|
||||
inv_label := gtk.NewLabel("")
|
||||
op.table.Attach(inv_label, 1, 2, 6, 7, gtk.EXPAND, gtk.FILL, 5, 5)
|
||||
|
||||
// Invisible thing.
|
||||
inv_label := gtk.NewLabel("")
|
||||
op.table.Attach(inv_label, 1, 2, 6, 7, gtk.EXPAND, gtk.FILL, 5, 5)
|
||||
// The buttons.
|
||||
buttons_box := gtk.NewHBox(false, 0)
|
||||
buttons_sep := gtk.NewHBox(false, 0)
|
||||
|
||||
// The buttons.
|
||||
buttons_box := gtk.NewHBox(false, 0)
|
||||
buttons_sep := gtk.NewHBox(false, 0)
|
||||
cancel_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("Cancel", nil))
|
||||
cancel_button.SetTooltipText(ctx.Translator.Translate("Close without saving", nil))
|
||||
cancel_button.Clicked(op.closeByCancel)
|
||||
buttons_box.PackStart(cancel_button, false, true, 5)
|
||||
|
||||
cancel_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("Cancel", nil))
|
||||
cancel_button.SetTooltipText(ctx.Translator.Translate("Close without saving", nil))
|
||||
cancel_button.Clicked(op.closeByCancel)
|
||||
buttons_box.PackStart(cancel_button, false, true, 5)
|
||||
buttons_box.PackStart(buttons_sep, true, true, 5)
|
||||
|
||||
buttons_box.PackStart(buttons_sep, true, true, 5)
|
||||
add_button := gtk.NewButton()
|
||||
if op.update {
|
||||
add_button.SetLabel(ctx.Translator.Translate("Update", nil))
|
||||
add_button.SetTooltipText(ctx.Translator.Translate("Update profile", nil))
|
||||
} else {
|
||||
add_button.SetLabel(ctx.Translator.Translate("Add", nil))
|
||||
add_button.SetTooltipText(ctx.Translator.Translate("Add profile", nil))
|
||||
}
|
||||
add_button.Clicked(op.saveProfile)
|
||||
buttons_box.PackStart(add_button, false, true, 5)
|
||||
|
||||
add_button := gtk.NewButton()
|
||||
if op.update {
|
||||
add_button.SetLabel(ctx.Translator.Translate("Update", nil))
|
||||
add_button.SetTooltipText(ctx.Translator.Translate("Update profile", nil))
|
||||
} else {
|
||||
add_button.SetLabel(ctx.Translator.Translate("Add", nil))
|
||||
add_button.SetTooltipText(ctx.Translator.Translate("Add profile", nil))
|
||||
}
|
||||
add_button.Clicked(op.saveProfile)
|
||||
buttons_box.PackStart(add_button, false, true, 5)
|
||||
vert_sep_box := gtk.NewVBox(false, 0)
|
||||
|
||||
vert_sep_box := gtk.NewVBox(false, 0)
|
||||
vbox := gtk.NewVBox(false, 0)
|
||||
vbox.PackStart(op.table, false, true, 5)
|
||||
vbox.PackStart(vert_sep_box, true, true, 5)
|
||||
vbox.PackStart(buttons_box, false, true, 5)
|
||||
|
||||
vbox := gtk.NewVBox(false, 0)
|
||||
vbox.PackStart(op.table, false, true, 5)
|
||||
vbox.PackStart(vert_sep_box, true, true, 5)
|
||||
vbox.PackStart(buttons_box, false, true, 5)
|
||||
|
||||
op.window.Add(vbox)
|
||||
op.window.ShowAll()
|
||||
op.window.Add(vbox)
|
||||
op.window.ShowAll()
|
||||
}
|
||||
|
||||
func (op *OptionsProfile) InitializeUpdate(profile_name string) {
|
||||
fmt.Println("Updating profile '" + profile_name + "'")
|
||||
op.Initialize(true)
|
||||
fmt.Println("Updating profile '" + profile_name + "'")
|
||||
op.Initialize(true)
|
||||
|
||||
// Get profile data.
|
||||
profile := ctx.Cache.Profiles[profile_name].Profile
|
||||
op.profile_name.SetText(profile.Name)
|
||||
op.binary_path.SetText(profile.Binary)
|
||||
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" {
|
||||
op.another_x_session.SetActive(true)
|
||||
}
|
||||
// Get profile data.
|
||||
profile := ctx.Cache.Profiles[profile_name].Profile
|
||||
op.profile_name.SetText(profile.Name)
|
||||
op.binary_path.SetText(profile.Binary)
|
||||
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" {
|
||||
op.another_x_session.SetActive(true)
|
||||
}
|
||||
|
||||
if profile.Version == "4.3.1" {
|
||||
op.urt_version_combo.SetActive(1)
|
||||
} else if profile.Version == "4.3.2" {
|
||||
op.urt_version_combo.SetActive(2)
|
||||
} else {
|
||||
op.urt_version_combo.SetActive(0)
|
||||
}
|
||||
if profile.Version == "4.3.1" {
|
||||
op.urt_version_combo.SetActive(1)
|
||||
} else if profile.Version == "4.3.2" {
|
||||
op.urt_version_combo.SetActive(2)
|
||||
} else {
|
||||
op.urt_version_combo.SetActive(0)
|
||||
}
|
||||
|
||||
op.old_profile = profile
|
||||
op.old_profile = profile
|
||||
|
||||
}
|
||||
|
||||
func (op *OptionsProfile) saveProfile() {
|
||||
fmt.Println("Saving profile...")
|
||||
fmt.Println("Saving profile...")
|
||||
|
||||
// Validating fields.
|
||||
// Profile name must not be empty.
|
||||
if len(op.profile_name.GetText()) < 1 {
|
||||
mbox_string := ctx.Translator.Translate("Empty profile name!\nProfile must be named somehow.", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
// Binary path must also be filled.
|
||||
if len(op.binary_path.GetText()) < 1 {
|
||||
mbox_string := ctx.Translator.Translate("Empty path to binary!\nThis profile will be unusable if you\nwill not provide path to binary!", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
// ...and must be executable! :)
|
||||
_, err := os.Stat(op.binary_path.GetText())
|
||||
if err != nil {
|
||||
mbox_string := ctx.Translator.Translate("Invalid path to binary!\n\nError was:\n", nil) + err.Error() + ctx.Translator.Translate("\n\nCheck binary path and try again.", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
// ToDo: executable flag checking.
|
||||
//fmt.Println(filestat.Mode())
|
||||
profile_name := op.profile_name.GetText()
|
||||
// Validating fields.
|
||||
// Profile name must not be empty.
|
||||
if len(op.profile_name.GetText()) < 1 {
|
||||
mbox_string := ctx.Translator.Translate("Empty profile name!\nProfile must be named somehow.", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
// Binary path must also be filled.
|
||||
if len(op.binary_path.GetText()) < 1 {
|
||||
mbox_string := ctx.Translator.Translate("Empty path to binary!\nThis profile will be unusable if you\nwill not provide path to binary!", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
// ...and must be executable! :)
|
||||
_, err := os.Stat(op.binary_path.GetText())
|
||||
if err != nil {
|
||||
mbox_string := ctx.Translator.Translate("Invalid path to binary!\n\nError was:\n", nil) + err.Error() + ctx.Translator.Translate("\n\nCheck binary path and try again.", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
// ToDo: executable flag checking.
|
||||
//fmt.Println(filestat.Mode())
|
||||
profile_name := op.profile_name.GetText()
|
||||
|
||||
_, ok := ctx.Cache.Profiles[profile_name]
|
||||
if ok && !op.update {
|
||||
mbox_string := ctx.Translator.Translate("Game profile with same name already exist.\nRename profile for saving.", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
ctx.Cache.CreateProfile(profile_name)
|
||||
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()
|
||||
_, ok := ctx.Cache.Profiles[profile_name]
|
||||
if ok && !op.update {
|
||||
mbox_string := ctx.Translator.Translate("Game profile with same name already exist.\nRename profile for saving.", nil)
|
||||
m := gtk.NewMessageDialog(op.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
||||
m.Response(func() {
|
||||
m.Destroy()
|
||||
})
|
||||
m.Run()
|
||||
} else {
|
||||
ctx.Cache.CreateProfile(profile_name)
|
||||
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.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.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() {
|
||||
ctx.Cache.Profiles[profile_name].Profile.Second_x_session = "1"
|
||||
} else {
|
||||
ctx.Cache.Profiles[profile_name].Profile.Second_x_session = "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.Eventer.LaunchEvent("flushProfiles", nil)
|
||||
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
||||
ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
|
||||
op.window.Destroy()
|
||||
if op.another_x_session.GetActive() {
|
||||
ctx.Cache.Profiles[profile_name].Profile.Second_x_session = "1"
|
||||
} else {
|
||||
ctx.Cache.Profiles[profile_name].Profile.Second_x_session = "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.Eventer.LaunchEvent("flushProfiles", nil)
|
||||
ctx.Eventer.LaunchEvent("loadProfilesIntoOptionsWindow", map[string]string{})
|
||||
ctx.Eventer.LaunchEvent("loadProfilesIntoMainWindow", map[string]string{})
|
||||
op.window.Destroy()
|
||||
}
|
||||
|
@ -10,95 +10,95 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
"sort"
|
||||
// stdlib
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
// Local
|
||||
"github.com/pztrn/urtrator/ioq3dataparser"
|
||||
// Local
|
||||
"gitlab.com/pztrn/urtrator/ioq3dataparser"
|
||||
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
"github.com/mattn/go-gtk/glib"
|
||||
// Other
|
||||
"github.com/mattn/go-gtk/glib"
|
||||
"github.com/mattn/go-gtk/gtk"
|
||||
)
|
||||
|
||||
type ServerCVarsDialog struct {
|
||||
// Window.
|
||||
window *gtk.Window
|
||||
// Main Vertical Box.
|
||||
vbox *gtk.VBox
|
||||
// Treeview for CVars.
|
||||
treeview *gtk.TreeView
|
||||
// Store for treeview.
|
||||
treeview_store *gtk.ListStore
|
||||
// Window.
|
||||
window *gtk.Window
|
||||
// Main Vertical Box.
|
||||
vbox *gtk.VBox
|
||||
// Treeview for CVars.
|
||||
treeview *gtk.TreeView
|
||||
// Store for treeview.
|
||||
treeview_store *gtk.ListStore
|
||||
}
|
||||
|
||||
func (scd *ServerCVarsDialog) Close() {
|
||||
scd.window.Destroy()
|
||||
scd.window.Destroy()
|
||||
}
|
||||
|
||||
func (scd *ServerCVarsDialog) fill(srv_address string) {
|
||||
server_info := ctx.Cache.Servers[srv_address].Server
|
||||
parsed_general_data := ioq3dataparser.ParseInfoToMap(server_info.ExtendedConfig)
|
||||
server_info := ctx.Cache.Servers[srv_address].Server
|
||||
parsed_general_data := ioq3dataparser.ParseInfoToMap(server_info.ExtendedConfig)
|
||||
|
||||
// Sort it!
|
||||
general_data_keys := make([]string, 0, len(parsed_general_data))
|
||||
for k := range parsed_general_data {
|
||||
general_data_keys = append(general_data_keys, k)
|
||||
}
|
||||
// Sort it!
|
||||
general_data_keys := make([]string, 0, len(parsed_general_data))
|
||||
for k := range parsed_general_data {
|
||||
general_data_keys = append(general_data_keys, k)
|
||||
}
|
||||
|
||||
sort.Strings(general_data_keys)
|
||||
sort.Strings(general_data_keys)
|
||||
|
||||
for k := range general_data_keys {
|
||||
iter := new(gtk.TreeIter)
|
||||
scd.treeview_store.Append(iter)
|
||||
scd.treeview_store.SetValue(iter, 0, general_data_keys[k])
|
||||
scd.treeview_store.SetValue(iter, 1, parsed_general_data[general_data_keys[k]])
|
||||
}
|
||||
for k := range general_data_keys {
|
||||
iter := new(gtk.TreeIter)
|
||||
scd.treeview_store.Append(iter)
|
||||
scd.treeview_store.SetValue(iter, 0, general_data_keys[k])
|
||||
scd.treeview_store.SetValue(iter, 1, parsed_general_data[general_data_keys[k]])
|
||||
}
|
||||
}
|
||||
|
||||
func (scd *ServerCVarsDialog) Initialize(w *gtk.Window, srv_address string) {
|
||||
fmt.Println("Showing server's CVars...")
|
||||
fmt.Println("Showing server's CVars...")
|
||||
|
||||
scd.initializeStorages()
|
||||
scd.initializeStorages()
|
||||
|
||||
scd.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
|
||||
scd.window.SetTitle(ctx.Translator.Translate("URTrator - Server CVars", nil))
|
||||
scd.window.Connect("destroy", scd.Close)
|
||||
scd.window.SetTransientFor(w)
|
||||
scd.window.SetDefaultSize(300, 400)
|
||||
scd.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
|
||||
scd.window.SetTitle(ctx.Translator.Translate("URTrator - Server CVars", nil))
|
||||
scd.window.Connect("destroy", scd.Close)
|
||||
scd.window.SetTransientFor(w)
|
||||
scd.window.SetDefaultSize(300, 400)
|
||||
|
||||
scd.vbox = gtk.NewVBox(false, 0)
|
||||
scd.window.Add(scd.vbox)
|
||||
scd.vbox = gtk.NewVBox(false, 0)
|
||||
scd.window.Add(scd.vbox)
|
||||
|
||||
// CVars scrolls.
|
||||
si := gtk.NewScrolledWindow(nil, nil)
|
||||
scd.vbox.PackStart(si, true, true, 5)
|
||||
// CVars scrolls.
|
||||
si := gtk.NewScrolledWindow(nil, nil)
|
||||
scd.vbox.PackStart(si, true, true, 5)
|
||||
|
||||
// CVars list.
|
||||
scd.treeview = gtk.NewTreeView()
|
||||
scd.treeview.SetModel(scd.treeview_store)
|
||||
si.Add(scd.treeview)
|
||||
// CVars list.
|
||||
scd.treeview = gtk.NewTreeView()
|
||||
scd.treeview.SetModel(scd.treeview_store)
|
||||
si.Add(scd.treeview)
|
||||
|
||||
scd.treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes(ctx.Translator.Translate("Key", nil), gtk.NewCellRendererText(), "markup", 0))
|
||||
scd.treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes(ctx.Translator.Translate("Value", nil), gtk.NewCellRendererText(), "markup", 1))
|
||||
scd.treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes(ctx.Translator.Translate("Key", nil), gtk.NewCellRendererText(), "markup", 0))
|
||||
scd.treeview.AppendColumn(gtk.NewTreeViewColumnWithAttributes(ctx.Translator.Translate("Value", nil), gtk.NewCellRendererText(), "markup", 1))
|
||||
|
||||
// Close button.
|
||||
hbox := gtk.NewHBox(false, 0)
|
||||
scd.vbox.PackStart(hbox, false, true, 5)
|
||||
// Close button.
|
||||
hbox := gtk.NewHBox(false, 0)
|
||||
scd.vbox.PackStart(hbox, false, true, 5)
|
||||
|
||||
sep := gtk.NewHBox(false, 0)
|
||||
hbox.PackStart(sep, true, true, 5)
|
||||
sep := gtk.NewHBox(false, 0)
|
||||
hbox.PackStart(sep, true, true, 5)
|
||||
|
||||
close_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("Close", nil))
|
||||
close_button.Clicked(scd.Close)
|
||||
hbox.PackStart(close_button, false, true, 5)
|
||||
close_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("Close", nil))
|
||||
close_button.Clicked(scd.Close)
|
||||
hbox.PackStart(close_button, false, true, 5)
|
||||
|
||||
scd.fill(srv_address)
|
||||
scd.fill(srv_address)
|
||||
|
||||
scd.window.ShowAll()
|
||||
scd.window.ShowAll()
|
||||
}
|
||||
|
||||
func (scd *ServerCVarsDialog) initializeStorages() {
|
||||
scd.treeview_store = gtk.NewListStore(glib.G_TYPE_STRING, glib.G_TYPE_STRING)
|
||||
scd.treeview_store = gtk.NewListStore(glib.G_TYPE_STRING, glib.G_TYPE_STRING)
|
||||
}
|
||||
|
30
urtrator.go
30
urtrator.go
@ -10,26 +10,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
// local
|
||||
"github.com/pztrn/urtrator/common"
|
||||
"github.com/pztrn/urtrator/context"
|
||||
"github.com/pztrn/urtrator/ui/gtk2"
|
||||
//"github.com/pztrn/urtrator/ui/qt5"
|
||||
// local
|
||||
"gitlab.com/pztrn/urtrator/common"
|
||||
"gitlab.com/pztrn/urtrator/context"
|
||||
"gitlab.com/pztrn/urtrator/ui/gtk2"
|
||||
//"github.com/pztrn/urtrator/ui/qt5"
|
||||
|
||||
// stdlib
|
||||
"fmt"
|
||||
"runtime"
|
||||
// stdlib
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("This is URTrator, version " + common.URTRATOR_VERSION)
|
||||
fmt.Println("This is URTrator, version " + common.URTRATOR_VERSION)
|
||||
|
||||
numCPUs := runtime.NumCPU()
|
||||
runtime.GOMAXPROCS(numCPUs)
|
||||
numCPUs := runtime.NumCPU()
|
||||
runtime.GOMAXPROCS(numCPUs)
|
||||
|
||||
ctx := context.New()
|
||||
ctx.Initialize()
|
||||
ctx := context.New()
|
||||
ctx.Initialize()
|
||||
|
||||
ui := ui.NewMainWindow(ctx)
|
||||
ui.Initialize()
|
||||
ui := ui.NewMainWindow(ctx)
|
||||
ui.Initialize()
|
||||
}
|
||||
|
Reference in New Issue
Block a user