Updated to latest GTK2 bindings API and moved to Gitlab.

This commit is contained in:
Stanislav Nikitin 2018-11-10 13:21:53 +05:00
parent 070aa50762
commit 127e1b8ab9
27 changed files with 3347 additions and 3351 deletions

50
cache/cache_object.go vendored
View File

@ -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)
}

View File

@ -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
View File

@ -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
View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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>

View File

@ -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()
}
}()
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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 = `

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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()
}