This repository has been archived on 2022-06-29. You can view files and clone it, but cannot push or open issues or pull requests.
urtrator/ui/gtk2/mainwindow.go

855 lines
31 KiB
Go

// URTrator - Urban Terror server browser and game launcher, written in
// Go.
//
// Copyright (c) 2016-2020, Stanslav N. a.k.a pztrn (or p0z1tr0n) and
// URTrator contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject
// to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package ui
import (
// stdlib
"fmt"
"runtime"
"sort"
"strconv"
"strings"
// Local
"go.dev.pztrn.name/urtrator/datamodels"
"go.dev.pztrn.name/urtrator/ioq3dataparser"
// Other
"github.com/mattn/go-gtk/gdkpixbuf"
"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
)
type MainWindow struct {
// Gamemodes.
gamemodes map[string]string
text string
// Widgets.
// The window itself.
window *gtk.Window
// Vertical Box.
vbox *gtk.VBox
// Main menu.
menubar *gtk.MenuBar
// Toolbar
toolbar *gtk.Toolbar
// Horizontal box for main window.
hpane *gtk.HPaned
// Tab widget.
tab_widget *gtk.Notebook
// Tabs list.
tabs map[string]*gtk.Frame
// All servers widget.
all_servers *gtk.TreeView
// Favorite servers widget.
fav_servers *gtk.TreeView
// Statusbar.
statusbar *gtk.Statusbar
// Statusbar context ID.
statusbar_context_id uint
// Profiles combobox.
profiles *gtk.ComboBoxText
// Checkbox for hiding/showing offline servers in 'Servers' tab list.
all_servers_hide_offline *gtk.CheckButton
// Checkbox for hiding/showing passworded servers in 'Servers' tab list.
all_servers_hide_private *gtk.CheckButton
// Combobox for filtering server's versions.
all_servers_version *gtk.ComboBoxText
// Combobox for filtering by gamemode.
all_servers_gamemode *gtk.ComboBoxText
// Checkbox for hiding/showing offline servers in 'Favorites' tab list.
fav_servers_hide_offline *gtk.CheckButton
// Checkbox for hiding/showing passworded servers in 'Favorites' tab list.
fav_servers_hide_private *gtk.CheckButton
// Combobox for filtering server's versions.
fav_servers_version *gtk.ComboBoxText
// Combobox for filtering by gamemode.
fav_servers_gamemode *gtk.ComboBoxText
// Game launch button.
launch_button *gtk.Button
// Server's main information.
server_info *gtk.TreeView
// Players information.
players_info *gtk.TreeView
// Quick connect: server address
qc_server_address *gtk.Entry
// Quick connect: password
qc_password *gtk.Entry
// Quick connect: nickname
qc_nickname *gtk.Entry
// Tray icon.
tray_icon *gtk.StatusIcon
// Tray menu.
tray_menu *gtk.Menu
// Toolbar's label.
toolbar_label *gtk.Label
// Storages.
// All servers store.
all_servers_store *gtk.ListStore
// All servers sortable store.
all_servers_store_sortable *gtk.TreeSortable
// Favorites
fav_servers_store *gtk.ListStore
// Server's information store.
server_info_store *gtk.ListStore
// Players information store.
players_info_store *gtk.ListStore
// Dialogs.
options_dialog *OptionsDialog
server_cvars_dialog *ServerCVarsDialog
// Other
// Old profiles count.
old_profiles_count int
// Window size.
window_width int
window_height int
// Window position.
window_pos_x int
window_pos_y int
// Main pane delimiter position. It is calculated like:
//
// window_width - pane_position
//
// so we will get same right pane width even if we will resize
// main window. On resize and restore it will be set like:
//
// window_width - m.pane_negative_position
pane_negative_position int
// Columns names for servers tabs.
column_names map[string]string
// Real columns positions on servers tabs.
column_pos map[string]map[string]int
// Resources.
// Pixbufs.
// For unavailable (e.g. offline) server.
server_offline_pic *gdkpixbuf.Pixbuf
// For online server.
server_online_pic *gdkpixbuf.Pixbuf
// For private (passworded) server.
server_private_pic *gdkpixbuf.Pixbuf
// For public server
server_public_pic *gdkpixbuf.Pixbuf
// Flags.
// Application is initialized?
initialized bool
// Window is hidden?
hidden bool
// Use other's tab information?
// Used when user changed active tab, to show information about
// server which is selected on activated tab.
use_other_servers_tab bool
// Does servers updating already in progress?
// This helps to prevent random crashes when more than one
// updating process in progress.
servers_already_updating bool
}
func (m *MainWindow) addToFavorites() {
fmt.Println("Adding server to favorites...")
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
server_address := ""
if !strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
server_address = m.getIpFromServersList(current_tab)
}
// Getting server from database.
fd := &FavoriteDialog{}
if len(server_address) > 0 {
servers := []datamodels.Server{}
address := strings.Split(server_address, ":")[0]
port := strings.Split(server_address, ":")[1]
err1 := ctx.Database.Db.Select(&servers, ctx.Database.Db.Rebind("SELECT * FROM servers WHERE ip=? AND port=?"), address, port)
if err1 != nil {
fmt.Println(err1.Error())
}
fd.InitializeUpdate(&servers[0])
} else {
fd.InitializeNew()
}
}
func (m *MainWindow) allServersGamemodeFilterChanged() {
ctx.Cfg.Cfg["/serverslist/all_servers/gamemode"] = strconv.Itoa(m.all_servers_gamemode.GetActive())
ctx.Eventer.LaunchEvent("loadAllServers", nil)
}
func (m *MainWindow) allServersVersionFilterChanged() {
ctx.Cfg.Cfg["/serverslist/all_servers/version"] = strconv.Itoa(m.all_servers_version.GetActive())
ctx.Eventer.LaunchEvent("loadAllServers", nil)
}
// Executes when delimiter for two panes is moved, to calculate VALID
// position.
func (m *MainWindow) checkMainPanePosition() {
glib.IdleAdd(func() bool {
m.pane_negative_position = m.window_width - m.hpane.GetPosition()
return false
})
}
// Executes when main window is moved or resized.
// Also calculating pane delimiter position and set it to avoid
// widgets hell :).
func (m *MainWindow) checkPositionAndSize() {
glib.IdleAdd(func() bool {
m.window_pos_x, m.window_pos_y = m.window.GetPosition()
m.window_width, m.window_height = m.window.GetSize()
m.hpane.SetPosition(m.window_width - m.pane_negative_position)
return false
})
}
// Executes on URTrator shutdown.
func (m *MainWindow) Close() {
// Save window parameters.
ctx.Cfg.Cfg["/mainwindow/width"] = strconv.Itoa(m.window_width)
ctx.Cfg.Cfg["/mainwindow/height"] = strconv.Itoa(m.window_height)
ctx.Cfg.Cfg["/mainwindow/position_x"] = strconv.Itoa(m.window_pos_x)
ctx.Cfg.Cfg["/mainwindow/position_y"] = strconv.Itoa(m.window_pos_y)
ctx.Cfg.Cfg["/mainwindow/pane_negative_position"] = strconv.Itoa(m.pane_negative_position)
// Saving columns sizes and positions.
all_servers_columns := m.all_servers.GetColumns()
for i := range all_servers_columns {
ctx.Cfg.Cfg["/mainwindow/all_servers/"+all_servers_columns[i].GetTitle()+"_position"] = strconv.Itoa(i)
ctx.Cfg.Cfg["/mainwindow/all_servers/"+all_servers_columns[i].GetTitle()+"_width"] = strconv.Itoa(all_servers_columns[i].GetWidth())
}
fav_servers_columns := m.fav_servers.GetColumns()
for i := range fav_servers_columns {
ctx.Cfg.Cfg["/mainwindow/fav_servers/"+fav_servers_columns[i].GetTitle()+"_position"] = strconv.Itoa(i)
ctx.Cfg.Cfg["/mainwindow/fav_servers/"+fav_servers_columns[i].GetTitle()+"_width"] = strconv.Itoa(fav_servers_columns[i].GetWidth())
}
// Additional actions should be taken on Windows.
if runtime.GOOS == "windows" {
m.closeWin()
}
ctx.Close()
}
func (m *MainWindow) copyServerCredentialsToClipboard() {
fmt.Println("Copying server's credentials to clipboard...")
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
server_address := m.getIpFromServersList(current_tab)
ctx.Clipboard.CopyServerData(server_address)
}
// Deleting server from favorites.
func (m *MainWindow) deleteFromFavorites() {
fmt.Println("Removing server from favorites...")
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
server_address := m.getIpFromServersList(current_tab)
var not_favorited bool = false
if len(server_address) > 0 {
if ctx.Cache.Servers[server_address].Server.Favorite == "1" {
ctx.Cache.Servers[server_address].Server.Favorite = "0"
} else {
not_favorited = true
}
} else {
not_favorited = true
}
if not_favorited {
// 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("Cannot delete server from favorites.\n\nServer isn't favorited.", nil)
d := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, mbox_string)
d.Response(func() {
d.Destroy()
})
d.Run()
} else {
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Server isn't favorited", nil) + "</span></markup>"})
}
}
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
}
// Drop database data.
// ToDo: extend so we should have an ability to decide what to drop.
func (m *MainWindow) dropDatabasesData() {
fmt.Println("Dropping database data...")
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("You are about to drop whole database data.\n\nAfter clicking \"YES\" ALL data in database (servers, profiles, settings, etc.)\nwill be lost FOREVER. Are you sure?", nil)
d := gtk.NewMessageDialog(m.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, mbox_string)
d.Connect("response", func(resp *glib.CallbackContext) {
if resp.Args(0) == 4294967287 {
will_continue = false
} else {
will_continue = true
}
d.Destroy()
})
d.Run()
} else {
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Remove ~/.config/urtrator/database.sqlite3 manually!", nil) + "</span></markup>"})
}
if will_continue {
ctx.Database.Db.MustExec("DELETE FROM servers")
ctx.Database.Db.MustExec("DELETE FROM settings")
ctx.Database.Db.MustExec("DELETE FROM urt_profiles")
ctx.Eventer.LaunchEvent("loadProfiles", map[string]string{})
ctx.Eventer.LaunchEvent("loadAllServers", map[string]string{})
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
}
}
// Executes on "Edit favorite server" click.
func (m *MainWindow) editFavorite() {
fmt.Println("Editing favorite server...")
server_address := m.getIpFromServersList("Favorites")
if len(server_address) > 0 {
srv := ctx.Cache.Servers[server_address].Server
fd := FavoriteDialog{}
fd.InitializeUpdate(srv)
}
}
func (m *MainWindow) favServersGamemodeFilterChanged() {
ctx.Cfg.Cfg["/serverslist/favorite/gamemode"] = strconv.Itoa(m.fav_servers_gamemode.GetActive())
ctx.Eventer.LaunchEvent("loadFavoriteServers", nil)
}
func (m *MainWindow) favServersVersionFilterChanged() {
ctx.Cfg.Cfg["/serverslist/favorite/version"] = strconv.Itoa(m.fav_servers_version.GetActive())
ctx.Eventer.LaunchEvent("loadFavoriteServers", nil)
}
// Executes when "Hide offline servers" checkbox changed it's state on
// "Servers" tab.
func (m *MainWindow) hideOfflineAllServers() {
fmt.Println("(Un)Hiding offline servers in 'Servers' tab...")
if m.all_servers_hide_offline.GetActive() {
ctx.Cfg.Cfg["/serverslist/all_servers/hide_offline"] = "1"
} else {
ctx.Cfg.Cfg["/serverslist/all_servers/hide_offline"] = "0"
}
ctx.Eventer.LaunchEvent("loadAllServers", map[string]string{})
}
// Executes when "Hide passworded servers" checkbox changed it's state on
// "Servers" tab.
func (m *MainWindow) hidePrivateAllServers() {
fmt.Println("(Un)Hiding private servers in 'Servers' tab...")
if m.all_servers_hide_private.GetActive() {
ctx.Cfg.Cfg["/serverslist/all_servers/hide_private"] = "1"
} else {
ctx.Cfg.Cfg["/serverslist/all_servers/hide_private"] = "0"
}
ctx.Eventer.LaunchEvent("loadAllServers", map[string]string{})
}
// Executes when "Hide offline servers" checkbox changed it's state on
// "Favorites" tab.
func (m *MainWindow) hideOfflineFavoriteServers() {
fmt.Println("(Un)Hiding offline servers in 'Favorite' tab...")
if m.fav_servers_hide_offline.GetActive() {
ctx.Cfg.Cfg["/serverslist/favorite/hide_offline"] = "1"
} else {
ctx.Cfg.Cfg["/serverslist/favorite/hide_offline"] = "0"
}
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
}
// Executes when "Hide passworded servers" checkbox changed it's state on
// "Favorites" tab.
func (m *MainWindow) hidePrivateFavoriteServers() {
fmt.Println("(Un)Hiding private servers in 'Favorite' tab...")
if m.all_servers_hide_private.GetActive() {
ctx.Cfg.Cfg["/serverslist/favorite/hide_private"] = "1"
} else {
ctx.Cfg.Cfg["/serverslist/favorite/hide_private"] = "0"
}
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
}
func (m *MainWindow) loadAllServers(data map[string]string) {
fmt.Println("Loading all servers...")
for _, server := range ctx.Cache.Servers {
iter := new(gtk.TreeIter)
ping, _ := strconv.Atoi(server.Server.Ping)
if !server.AllServersIterSet {
server.AllServersIter = iter
server.AllServersIterSet = true
} else {
iter = server.AllServersIter
}
// Hide offline servers?
if m.all_servers_hide_offline.GetActive() && (server.Server.Players == "" && server.Server.Maxplayers == "" || ping > 9000) {
if server.AllServersIterInList && server.AllServersIterSet {
m.all_servers_store.Remove(iter)
server.AllServersIterInList = false
}
continue
}
// Hide private servers?
if m.all_servers_hide_private.GetActive() && server.Server.IsPrivate == "1" {
if server.AllServersIterInList && server.AllServersIterSet {
m.all_servers_store.Remove(iter)
server.AllServersIterInList = false
}
continue
}
// Hide servers that using different version than selected in
// filter?
if m.all_servers_version.GetActiveText() != ctx.Translator.Translate("All versions", nil) && m.all_servers_version.GetActiveText() != server.Server.Version {
if server.AllServersIterInList && server.AllServersIterSet {
m.all_servers_store.Remove(iter)
server.AllServersIterInList = false
}
continue
}
// Hide servers that using different gamemode than selected in
// filter?
gm_int_as_str := strconv.Itoa(m.all_servers_gamemode.GetActive())
if m.all_servers_gamemode.GetActiveText() != ctx.Translator.Translate("All gamemodes", nil) && gm_int_as_str != server.Server.Gamemode {
if server.AllServersIterInList && server.AllServersIterSet {
m.all_servers_store.Remove(iter)
server.AllServersIterInList = false
}
continue
}
if !server.AllServersIterInList && server.AllServersIterSet {
m.all_servers_store.Append(iter)
server.AllServersIterInList = true
}
if server.Server.Name == "" && server.Server.Players == "" {
m.all_servers_store.SetValue(iter, 0, m.server_offline_pic.GPixbuf)
m.all_servers_store.SetValue(iter, m.column_pos["Servers"][ctx.Translator.Translate("IP", nil)], server.Server.Ip+":"+server.Server.Port)
} else {
if ping > 9000 {
m.all_servers_store.SetValue(iter, 0, m.server_offline_pic.GPixbuf)
} else {
m.all_servers_store.SetValue(iter, 0, m.server_online_pic.GPixbuf)
}
if server.Server.IsPrivate == "1" {
m.all_servers_store.SetValue(iter, 1, m.server_private_pic.GPixbuf)
} else {
m.all_servers_store.SetValue(iter, 1, m.server_public_pic.GPixbuf)
}
server_name := ctx.Colorizer.Fix(server.Server.Name)
m.all_servers_store.SetValue(iter, m.column_pos["Servers"][ctx.Translator.Translate("Name", nil)], server_name)
m.all_servers_store.SetValue(iter, m.column_pos["Servers"][ctx.Translator.Translate("Mode", nil)], m.getGameModeName(server.Server.Gamemode))
m.all_servers_store.SetValue(iter, m.column_pos["Servers"][ctx.Translator.Translate("Map", nil)], server.Server.Map)
m.all_servers_store.SetValue(iter, m.column_pos["Servers"][ctx.Translator.Translate("Players", nil)], server.Server.Players+"/"+server.Server.Bots+"/"+server.Server.Maxplayers)
m.all_servers_store.SetValue(iter, m.column_pos["Servers"][ctx.Translator.Translate("Ping", nil)], server.Server.Ping)
m.all_servers_store.SetValue(iter, m.column_pos["Servers"][ctx.Translator.Translate("Version", nil)], server.Server.Version)
m.all_servers_store.SetValue(iter, m.column_pos["Servers"][ctx.Translator.Translate("IP", nil)], server.Server.Ip+":"+server.Server.Port)
}
}
}
func (m *MainWindow) loadFavoriteServers(data map[string]string) {
fmt.Println("Loading favorite servers...")
for _, server := range ctx.Cache.Servers {
iter := new(gtk.TreeIter)
ping, _ := strconv.Atoi(server.Server.Ping)
if !server.FavServersIterSet {
server.FavServersIter = iter
server.FavServersIterSet = true
} else {
iter = server.FavServersIter
}
// Hide offline servers?
if m.fav_servers_hide_offline.GetActive() && (server.Server.Players == "" && server.Server.Maxplayers == "" || ping > 9000) {
if server.FavServersIterInList {
m.fav_servers_store.Remove(iter)
server.FavServersIterInList = false
}
continue
}
// Hide private servers?
if m.fav_servers_hide_private.GetActive() && server.Server.IsPrivate == "1" {
if server.FavServersIterInList && server.FavServersIterSet {
m.fav_servers_store.Remove(iter)
server.FavServersIterInList = false
}
continue
}
// Hide servers that using different version than selected in
// filter?
if m.fav_servers_version.GetActiveText() != ctx.Translator.Translate("All versions", nil) && m.fav_servers_version.GetActiveText() != server.Server.Version {
if server.FavServersIterInList && server.FavServersIterSet {
m.fav_servers_store.Remove(iter)
server.FavServersIterInList = false
}
continue
}
// Hide servers that using different gamemode than selected in
// filter?
gm_int_as_str := strconv.Itoa(m.fav_servers_gamemode.GetActive())
if m.fav_servers_gamemode.GetActiveText() != ctx.Translator.Translate("All gamemodes", nil) && gm_int_as_str != server.Server.Gamemode {
if server.FavServersIterInList && server.FavServersIterSet {
m.fav_servers_store.Remove(iter)
server.FavServersIterInList = false
}
continue
}
// If server on favorites widget, but not favorited (e.g. just
// removed from favorites) - remove it from list.
if server.Server.Favorite != "1" && server.FavServersIterSet && server.FavServersIterInList {
m.fav_servers_store.Remove(server.FavServersIter)
server.FavServersIterInList = false
server.FavServersIterSet = false
}
// Server isn't in favorites and wasn't previously added to widget.
if server.Server.Favorite != "1" {
continue
}
if !server.FavServersIterInList && server.FavServersIterSet {
m.fav_servers_store.Append(iter)
server.FavServersIterInList = true
}
if server.Server.Name == "" && server.Server.Players == "" {
m.fav_servers_store.SetValue(iter, 0, m.server_offline_pic.GPixbuf)
m.fav_servers_store.SetValue(iter, m.column_pos["Favorites"][ctx.Translator.Translate("IP", nil)], server.Server.Ip+":"+server.Server.Port)
} else {
if ping > 9000 {
m.fav_servers_store.SetValue(iter, 0, m.server_offline_pic.GPixbuf)
} else {
m.fav_servers_store.SetValue(iter, 0, m.server_online_pic.GPixbuf)
}
if server.Server.IsPrivate == "1" {
m.fav_servers_store.SetValue(iter, 1, m.server_private_pic.GPixbuf)
} else {
m.fav_servers_store.SetValue(iter, 1, m.server_public_pic.GPixbuf)
}
server_name := ctx.Colorizer.Fix(server.Server.Name)
m.fav_servers_store.SetValue(iter, m.column_pos["Favorites"][ctx.Translator.Translate("Name", nil)], server_name)
m.fav_servers_store.SetValue(iter, m.column_pos["Favorites"][ctx.Translator.Translate("Mode", nil)], m.getGameModeName(server.Server.Gamemode))
m.fav_servers_store.SetValue(iter, m.column_pos["Favorites"][ctx.Translator.Translate("Map", nil)], server.Server.Map)
m.fav_servers_store.SetValue(iter, m.column_pos["Favorites"][ctx.Translator.Translate("Players", nil)], server.Server.Players+"/"+server.Server.Bots+"/"+server.Server.Maxplayers)
m.fav_servers_store.SetValue(iter, m.column_pos["Favorites"][ctx.Translator.Translate("Ping", nil)], server.Server.Ping)
m.fav_servers_store.SetValue(iter, m.column_pos["Favorites"][ctx.Translator.Translate("Version", nil)], server.Server.Version)
m.fav_servers_store.SetValue(iter, m.column_pos["Favorites"][ctx.Translator.Translate("IP", nil)], server.Server.Ip+":"+server.Server.Port)
}
}
}
func (m *MainWindow) loadProfiles(data map[string]string) {
fmt.Println("Loading profiles into combobox on MainWindow")
for i := 0; i < m.old_profiles_count; i++ {
// ComboBox indexes are shifting on element deletion, so we should
// detele very first element every time.
m.profiles.Remove(0)
}
for _, profile := range ctx.Cache.Profiles {
m.profiles.AppendText(profile.Profile.Name)
}
m.old_profiles_count = len(ctx.Cache.Profiles)
fmt.Println("Added " + strconv.Itoa(m.old_profiles_count) + " profiles")
m.profiles.SetActive(0)
}
func (m *MainWindow) tabChanged() {
if !m.initialized {
return
}
fmt.Println("Active tab changed...")
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
fmt.Println(current_tab)
m.use_other_servers_tab = true
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
m.fav_servers.Emit("cursor-changed")
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
m.all_servers.Emit("cursor-changed")
}
m.use_other_servers_tab = false
}
func (m *MainWindow) serversUpdateCompleted(data map[string]string) {
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": ctx.Translator.Translate("Servers updated.", nil)})
// Trigger "selection-changed" events on currently active tab's
// servers list.
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
m.all_servers.Emit("cursor-changed")
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
m.fav_servers.Emit("cursor-changed")
}
m.servers_already_updating = false
}
func (m *MainWindow) setQuickConnectDetails(data map[string]string) {
fmt.Println("Setting quick connect data...")
m.qc_server_address.SetText(data["server"])
m.qc_password.SetText(data["password"])
}
func (m *MainWindow) setToolbarLabelText(data map[string]string) {
fmt.Println("Setting toolbar's label text...")
if strings.Contains(data["text"], "<markup>") {
fmt.Println("With markup")
m.toolbar_label.SetMarkup(data["text"])
} else {
fmt.Println("Without markup")
m.toolbar_label.SetLabel(data["text"])
}
}
func (m *MainWindow) showHide() {
if m.hidden {
m.window.Show()
m.hidden = false
// Set window position on restore. Window loosing it on
// multimonitor configurations.
m.window.Move(m.window_pos_x, m.window_pos_y)
} else {
m.window.Hide()
m.hidden = true
}
}
func (m *MainWindow) showServerCVars() {
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
if m.use_other_servers_tab {
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
current_tab = "Favorites"
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
current_tab = "Servers"
}
}
srv_address := m.getIpFromServersList(current_tab)
if len(srv_address) > 0 {
m.server_cvars_dialog.Initialize(m.window, srv_address)
}
}
func (m *MainWindow) showShortServerInformation() {
fmt.Println("Server selection changed, updating server's information widget...")
m.server_info_store.Clear()
m.players_info_store.Clear()
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
if m.use_other_servers_tab {
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
current_tab = "Favorites"
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
current_tab = "Servers"
}
}
srv_address := m.getIpFromServersList(current_tab)
// Getting server information from cache.
if len(srv_address) > 0 && ctx.Cache.Servers[srv_address].Server.Players != "" {
server_info := ctx.Cache.Servers[srv_address].Server
parsed_general_data := ioq3dataparser.ParseInfoToMap(server_info.ExtendedConfig)
parsed_players_info := ioq3dataparser.ParsePlayersInfoToMap(server_info.PlayersInfo)
// Append to treeview generic info first. After appending it
// will be deleted from map.
// Server's name.
iter := new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, ctx.Translator.Translate("Server's name", nil))
m.server_info_store.SetValue(iter, 1, ctx.Colorizer.Fix(parsed_general_data["sv_hostname"]))
delete(parsed_general_data, "sv_hostname")
// Game version.
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, ctx.Translator.Translate("Game version", nil))
m.server_info_store.SetValue(iter, 1, parsed_general_data["g_modversion"])
delete(parsed_general_data, "g_modversion")
// Players.
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, ctx.Translator.Translate("Players", nil))
m.server_info_store.SetValue(iter, 1, server_info.Players+" of "+parsed_general_data["sv_maxclients"]+" ("+server_info.Bots+" bots)")
delete(parsed_general_data, "sv_maxclients")
// Ping
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, ctx.Translator.Translate("Ping", nil))
m.server_info_store.SetValue(iter, 1, server_info.Ping+" ms")
// Game mode
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, ctx.Translator.Translate("Game mode", nil))
m.server_info_store.SetValue(iter, 1, m.gamemodes[server_info.Gamemode])
// Map name
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, ctx.Translator.Translate("Current map", nil))
m.server_info_store.SetValue(iter, 1, server_info.Map)
// Private or public?
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, ctx.Translator.Translate("Passworded", nil))
passworded_status := "<markup><span foreground=\"green\">" + ctx.Translator.Translate("No", nil) + "</span></markup>"
if server_info.IsPrivate == "1" {
passworded_status = "<markup><span foreground=\"red\">" + ctx.Translator.Translate("Yes", nil) + "</span></markup>"
}
m.server_info_store.SetValue(iter, 1, passworded_status)
// Sorting keys of map.
players_map_keys := make([]string, 0, len(parsed_players_info))
for k := range parsed_players_info {
// ToDo: figure out how to do this properly without
// append().
players_map_keys = append(players_map_keys, k)
}
sort.Strings(players_map_keys)
for k := range players_map_keys {
iter = new(gtk.TreeIter)
nick := ctx.Colorizer.Fix(parsed_players_info[players_map_keys[k]]["nick"])
m.players_info_store.Append(iter)
m.players_info_store.SetValue(iter, 0, nick)
m.players_info_store.SetValue(iter, 1, parsed_players_info[players_map_keys[k]]["frags"])
m.players_info_store.SetValue(iter, 2, parsed_players_info[players_map_keys[k]]["ping"])
}
/*
// Just a separator.
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
// Other parameters :).
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, "<markup><span font_weight=\"bold\">OTHER PARAMETERS</span></markup>")
// 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)
for k := range general_data_keys {
iter = new(gtk.TreeIter)
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, general_data_keys[k])
m.server_info_store.SetValue(iter, 1, parsed_general_data[general_data_keys[k]])
}
*/
}
}
// Show tray menu on right-click on tray icon.
func (m *MainWindow) showTrayMenu(cbx *glib.CallbackContext) {
m.tray_menu.Popup(nil, nil, gtk.StatusIconPositionMenu, m.tray_icon, uint(cbx.Args(0)), uint32(cbx.Args(1)))
}
// Unlocking interface after game shut down.
func (m *MainWindow) unlockInterface() {
m.launch_button.SetSensitive(true)
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": ctx.Translator.Translate("URTrator is ready.", nil)})
}
func (m *MainWindow) updateOneServer() {
if m.servers_already_updating {
return
}
m.servers_already_updating = true
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Updating selected server...", nil) + "</span></markup>"})
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
srv_address := m.getIpFromServersList(current_tab)
if len(srv_address) > 0 {
go ctx.Requester.UpdateOneServer(srv_address)
}
}
// Triggered when "Update all servers" button is clicked.
func (m *MainWindow) UpdateServers() {
if m.servers_already_updating {
return
}
m.servers_already_updating = true
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Updating servers...", nil) + "</span></markup>"})
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
fmt.Println("Updating servers on tab '" + current_tab + "'...")
if strings.Contains(current_tab, ctx.Translator.Translate("Servers", nil)) {
go ctx.Requester.UpdateAllServers(false)
} else if strings.Contains(current_tab, ctx.Translator.Translate("Favorites", nil)) {
go ctx.Requester.UpdateFavoriteServers()
}
}
func (m *MainWindow) UpdateServersEventHandler(data map[string]string) {
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx.Translator.Translate("Updating servers...", nil) + "</span></markup>"})
go ctx.Requester.UpdateAllServers(true)
}