2018-11-10 21:13:06 +05:00
// URTrator - Urban Terror server browser and game launcher, written in
2016-10-04 15:42:36 +05:00
// Go.
//
2019-12-29 13:21:05 +05:00
// Copyright (c) 2016-2020, Stanslav N. a.k.a pztrn (or p0z1tr0n) and
2018-11-10 21:13:06 +05:00
// URTrator contributors.
2016-10-04 15:42:36 +05:00
//
2018-11-10 21:13:06 +05:00
// 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.
2016-10-04 15:42:36 +05:00
package ui
import (
2018-11-10 13:21:53 +05:00
// stdlib
"fmt"
"runtime"
"sort"
"strconv"
"strings"
// Local
2019-12-29 13:21:05 +05:00
"go.dev.pztrn.name/urtrator/datamodels"
"go.dev.pztrn.name/urtrator/ioq3dataparser"
2018-11-10 13:21:53 +05:00
// Other
"github.com/mattn/go-gtk/gdkpixbuf"
"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"
2016-10-04 15:42:36 +05:00
)
type MainWindow struct {
2018-11-10 13:21:53 +05:00
// 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
2016-10-04 15:42:36 +05:00
}
func ( m * MainWindow ) addToFavorites ( ) {
2018-11-10 13:21:53 +05:00
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 ( )
}
2016-10-04 15:42:36 +05:00
}
2016-11-26 16:20:57 +05:00
func ( m * MainWindow ) allServersGamemodeFilterChanged ( ) {
2018-11-10 13:21:53 +05:00
ctx . Cfg . Cfg [ "/serverslist/all_servers/gamemode" ] = strconv . Itoa ( m . all_servers_gamemode . GetActive ( ) )
ctx . Eventer . LaunchEvent ( "loadAllServers" , nil )
2016-11-26 16:20:57 +05:00
}
2016-11-26 16:00:17 +05:00
func ( m * MainWindow ) allServersVersionFilterChanged ( ) {
2018-11-10 13:21:53 +05:00
ctx . Cfg . Cfg [ "/serverslist/all_servers/version" ] = strconv . Itoa ( m . all_servers_version . GetActive ( ) )
ctx . Eventer . LaunchEvent ( "loadAllServers" , nil )
2016-11-26 16:00:17 +05:00
}
2016-10-06 13:55:03 +05:00
// Executes when delimiter for two panes is moved, to calculate VALID
// position.
2016-10-05 02:16:02 +05:00
func ( m * MainWindow ) checkMainPanePosition ( ) {
2018-11-10 13:21:53 +05:00
glib . IdleAdd ( func ( ) bool {
m . pane_negative_position = m . window_width - m . hpane . GetPosition ( )
return false
} )
2016-10-05 02:16:02 +05:00
}
2016-10-06 13:55:03 +05:00
// Executes when main window is moved or resized.
// Also calculating pane delimiter position and set it to avoid
// widgets hell :).
2016-10-05 02:16:02 +05:00
func ( m * MainWindow ) checkPositionAndSize ( ) {
2018-11-10 13:21:53 +05:00
glib . IdleAdd ( func ( ) bool {
m . window_pos_x , m . window_pos_y = m . window . GetPosition ( )
m . window_width , m . window_height = m . window . GetSize ( )
2016-10-05 02:16:02 +05:00
2018-11-10 13:21:53 +05:00
m . hpane . SetPosition ( m . window_width - m . pane_negative_position )
return false
} )
2016-10-05 02:16:02 +05:00
}
2016-10-06 13:55:03 +05:00
// Executes on URTrator shutdown.
2016-10-04 15:42:36 +05:00
func ( m * MainWindow ) Close ( ) {
2018-11-10 13:21:53 +05:00
// 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 ( )
2016-10-04 15:42:36 +05:00
}
2016-10-12 19:23:10 +05:00
func ( m * MainWindow ) copyServerCredentialsToClipboard ( ) {
2018-11-10 13:21:53 +05:00
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 )
2016-10-12 19:23:10 +05:00
}
2016-10-06 13:55:03 +05:00
// Deleting server from favorites.
2016-10-04 23:39:32 +05:00
func ( m * MainWindow ) deleteFromFavorites ( ) {
2018-11-10 13:21:53 +05:00
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 { } )
2016-10-04 23:39:32 +05:00
}
2016-10-06 13:55:03 +05:00
// Drop database data.
// ToDo: extend so we should have an ability to decide what to drop.
2016-10-04 23:39:32 +05:00
func ( m * MainWindow ) dropDatabasesData ( ) {
2018-11-10 13:21:53 +05:00
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 { } )
}
2016-10-04 23:39:32 +05:00
}
2016-10-06 13:55:03 +05:00
// Executes on "Edit favorite server" click.
2016-10-05 00:04:24 +05:00
func ( m * MainWindow ) editFavorite ( ) {
2018-11-10 13:21:53 +05:00
fmt . Println ( "Editing favorite server..." )
2016-10-05 00:04:24 +05:00
2018-11-10 13:21:53 +05:00
server_address := m . getIpFromServersList ( "Favorites" )
2016-10-05 00:04:24 +05:00
2018-11-10 13:21:53 +05:00
if len ( server_address ) > 0 {
srv := ctx . Cache . Servers [ server_address ] . Server
fd := FavoriteDialog { }
fd . InitializeUpdate ( srv )
}
2016-10-05 00:04:24 +05:00
}
2016-11-26 16:20:57 +05:00
func ( m * MainWindow ) favServersGamemodeFilterChanged ( ) {
2018-11-10 13:21:53 +05:00
ctx . Cfg . Cfg [ "/serverslist/favorite/gamemode" ] = strconv . Itoa ( m . fav_servers_gamemode . GetActive ( ) )
ctx . Eventer . LaunchEvent ( "loadFavoriteServers" , nil )
2016-11-26 16:20:57 +05:00
}
2016-11-26 16:00:17 +05:00
func ( m * MainWindow ) favServersVersionFilterChanged ( ) {
2018-11-10 13:21:53 +05:00
ctx . Cfg . Cfg [ "/serverslist/favorite/version" ] = strconv . Itoa ( m . fav_servers_version . GetActive ( ) )
ctx . Eventer . LaunchEvent ( "loadFavoriteServers" , nil )
2016-11-26 16:00:17 +05:00
}
2016-10-06 13:55:03 +05:00
// Executes when "Hide offline servers" checkbox changed it's state on
// "Servers" tab.
2016-10-04 15:42:36 +05:00
func ( m * MainWindow ) hideOfflineAllServers ( ) {
2018-11-10 13:21:53 +05:00
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 { } )
2016-10-04 15:42:36 +05:00
}
2016-11-23 09:49:39 +05:00
// Executes when "Hide passworded servers" checkbox changed it's state on
// "Servers" tab.
func ( m * MainWindow ) hidePrivateAllServers ( ) {
2018-11-10 13:21:53 +05:00
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 { } )
2016-11-23 09:49:39 +05:00
}
2016-10-06 13:55:03 +05:00
// Executes when "Hide offline servers" checkbox changed it's state on
// "Favorites" tab.
2016-10-04 15:42:36 +05:00
func ( m * MainWindow ) hideOfflineFavoriteServers ( ) {
2018-11-10 13:21:53 +05:00
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 { } )
2016-10-04 15:42:36 +05:00
}
2016-11-23 09:49:39 +05:00
// Executes when "Hide passworded servers" checkbox changed it's state on
// "Favorites" tab.
func ( m * MainWindow ) hidePrivateFavoriteServers ( ) {
2018-11-10 13:21:53 +05:00
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 { } )
2016-11-23 09:49:39 +05:00
}
2016-10-08 19:57:33 +05:00
func ( m * MainWindow ) loadAllServers ( data map [ string ] string ) {
2018-11-10 13:21:53 +05:00
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 )
}
}
2016-10-04 15:42:36 +05:00
}
2016-10-08 19:57:33 +05:00
func ( m * MainWindow ) loadFavoriteServers ( data map [ string ] string ) {
2018-11-10 13:21:53 +05:00
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 )
}
}
2016-10-04 23:39:32 +05:00
}
2016-10-08 19:57:33 +05:00
func ( m * MainWindow ) loadProfiles ( data map [ string ] string ) {
2018-11-10 13:21:53 +05:00
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 )
}
2016-10-04 23:39:32 +05:00
2018-11-10 13:21:53 +05:00
for _ , profile := range ctx . Cache . Profiles {
m . profiles . AppendText ( profile . Profile . Name )
}
2016-10-04 23:39:32 +05:00
2018-11-10 13:21:53 +05:00
m . old_profiles_count = len ( ctx . Cache . Profiles )
fmt . Println ( "Added " + strconv . Itoa ( m . old_profiles_count ) + " profiles" )
2016-11-22 18:33:53 +05:00
2018-11-10 13:21:53 +05:00
m . profiles . SetActive ( 0 )
2016-10-04 23:39:32 +05:00
}
2016-11-25 03:12:05 +05:00
func ( m * MainWindow ) tabChanged ( ) {
2018-11-10 13:21:53 +05:00
if ! m . initialized {
return
}
2016-11-25 03:12:05 +05:00
2018-11-10 13:21:53 +05:00
fmt . Println ( "Active tab changed..." )
current_tab := m . tab_widget . GetTabLabelText ( m . tab_widget . GetNthPage ( m . tab_widget . GetCurrentPage ( ) ) )
fmt . Println ( current_tab )
2016-11-25 03:12:05 +05:00
2018-11-10 13:21:53 +05:00
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
2016-11-25 03:12:05 +05:00
}
2016-10-08 19:57:33 +05:00
func ( m * MainWindow ) serversUpdateCompleted ( data map [ string ] string ) {
2018-11-10 13:21:53 +05:00
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 ( ) ) )
2016-11-23 10:10:11 +05:00
2018-11-10 13:21:53 +05:00
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" )
}
2016-11-23 10:10:11 +05:00
2018-11-10 13:21:53 +05:00
m . servers_already_updating = false
2017-05-08 23:38:54 +05:00
2016-10-08 19:57:33 +05:00
}
2016-10-11 13:14:08 +05:00
func ( m * MainWindow ) setQuickConnectDetails ( data map [ string ] string ) {
2018-11-10 13:21:53 +05:00
fmt . Println ( "Setting quick connect data..." )
m . qc_server_address . SetText ( data [ "server" ] )
m . qc_password . SetText ( data [ "password" ] )
2016-10-11 13:14:08 +05:00
}
2016-10-08 19:57:33 +05:00
func ( m * MainWindow ) setToolbarLabelText ( data map [ string ] string ) {
2018-11-10 13:21:53 +05:00
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" ] )
}
2016-10-06 13:55:03 +05:00
}
2016-10-05 01:03:46 +05:00
func ( m * MainWindow ) showHide ( ) {
2018-11-10 13:21:53 +05:00
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
}
2016-10-05 01:03:46 +05:00
}
2016-11-26 09:05:48 +05:00
func ( m * MainWindow ) showServerCVars ( ) {
2018-11-10 13:21:53 +05:00
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 )
}
2016-11-26 09:05:48 +05:00
}
2016-10-06 20:48:35 +05:00
func ( m * MainWindow ) showShortServerInformation ( ) {
2018-11-10 13:21:53 +05:00
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 ] ] )
}
* /
}
2016-10-06 20:48:35 +05:00
}
2016-10-06 17:11:36 +05:00
// Show tray menu on right-click on tray icon.
2016-10-05 01:03:46 +05:00
func ( m * MainWindow ) showTrayMenu ( cbx * glib . CallbackContext ) {
2018-11-10 13:21:53 +05:00
m . tray_menu . Popup ( nil , nil , gtk . StatusIconPositionMenu , m . tray_icon , uint ( cbx . Args ( 0 ) ) , uint32 ( cbx . Args ( 1 ) ) )
2016-10-05 01:03:46 +05:00
}
2016-10-06 17:11:36 +05:00
// Unlocking interface after game shut down.
2016-10-04 15:42:36 +05:00
func ( m * MainWindow ) unlockInterface ( ) {
2018-11-10 13:21:53 +05:00
m . launch_button . SetSensitive ( true )
ctx . Eventer . LaunchEvent ( "setToolbarLabelText" , map [ string ] string { "text" : ctx . Translator . Translate ( "URTrator is ready." , nil ) } )
2016-10-04 15:42:36 +05:00
}
2016-10-07 14:28:44 +05:00
func ( m * MainWindow ) updateOneServer ( ) {
2018-11-10 13:21:53 +05:00
if m . servers_already_updating {
return
}
m . servers_already_updating = true
2017-05-08 23:38:54 +05:00
2018-11-10 13:21:53 +05:00
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 )
2016-10-07 14:28:44 +05:00
2018-11-10 13:21:53 +05:00
if len ( srv_address ) > 0 {
go ctx . Requester . UpdateOneServer ( srv_address )
}
2016-10-07 14:28:44 +05:00
}
2016-10-06 13:55:03 +05:00
// Triggered when "Update all servers" button is clicked.
2016-10-04 15:42:36 +05:00
func ( m * MainWindow ) UpdateServers ( ) {
2018-11-10 13:21:53 +05:00
if m . servers_already_updating {
return
}
m . servers_already_updating = true
2017-05-08 23:38:54 +05:00
2018-11-10 13:21:53 +05:00
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 + "'..." )
2016-10-06 13:55:03 +05:00
2018-11-10 13:21:53 +05:00
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 ( )
}
2016-10-04 15:42:36 +05:00
}
2016-12-13 08:01:48 +05:00
func ( m * MainWindow ) UpdateServersEventHandler ( data map [ string ] string ) {
2018-11-10 13:21:53 +05:00
ctx . Eventer . LaunchEvent ( "setToolbarLabelText" , map [ string ] string { "text" : "<markup><span foreground=\"red\" font_weight=\"bold\">" + ctx . Translator . Translate ( "Updating servers..." , nil ) + "</span></markup>" } )
2016-12-13 08:01:48 +05:00
2018-11-10 13:21:53 +05:00
go ctx . Requester . UpdateAllServers ( true )
2016-12-13 08:01:48 +05:00
}