29 Commits

Author SHA1 Message Date
32c6297765 Fixed game version combobox not selecting proper version on profile editing. 2016-11-25 04:49:19 +05:00
190f76eb82 Fixed profiles editing crashing application if profile wasn't saved in database. 2016-11-25 04:44:46 +05:00
5c295f08ab Prettify options window. 2016-11-25 04:31:45 +05:00
061bfcaeb9 UI design updates.
Got rid of visible separators, replaced them with HBox and VBox.

Reworked profile add/edit window, now it looks prettier and
organic.
2016-11-25 04:11:44 +05:00
5ca8299714 Show selected server's information on active tab changing.
URTrator will now show information about selected server on
activated tab. E.g. when you switched from "Servers" to
"Favorites", sidebar informational widget will be updated with
server's data for selected server on "Favorites" tab.
2016-11-25 03:12:05 +05:00
9c8aa1cc34 Preparing to 0.1.0 release. 2016-11-23 10:13:01 +05:00
5fcbd8536c Update selected server's info in sidebar after updating server's data. 2016-11-23 10:10:11 +05:00
fb7a471aec Shw message in toolbar when updating selected server's data. 2016-11-23 10:02:58 +05:00
8c9d948a52 Fixed tooltip text for "Update all servers" button. 2016-11-23 09:53:09 +05:00
8b44d194b5 Hide private servers checkboxes. 2016-11-23 09:49:39 +05:00
3b0a93e63a By default srting players by name as well as cvars in sidebar. 2016-11-23 07:51:41 +05:00
b85ba0470c Fixed rendering of logo on launch button.
Also, made this logo smaller to beautify interface.
2016-11-23 07:42:58 +05:00
f127fdc9f4 Fixed players counting on servers update. 2016-11-23 07:41:14 +05:00
5ef54d943e Removed unneded "Additional information" button. 2016-11-23 07:35:10 +05:00
9e6cdfc869 Increased max ping requests to servers. Fixes #3. 2016-11-22 18:50:56 +05:00
bfd3f884b3 Automatic profile selection. Fixes #14.
Automatically select first added profile on every profiles list
update. Yes, quick hack. In future we will autodetect profiles
based on server version, and profiles combobox will only be
needed for quick connect.
2016-11-22 18:33:53 +05:00
7e6b698c1c Proper sorting by servers names. Fixing #12. 2016-11-22 18:23:43 +05:00
4516abb916 go-gtk fixed default sorting, so unlock it for all OSes. 2016-11-22 17:14:02 +05:00
e731653652 Fix for previous commit, wrong sorting call was masked on Windows. 2016-11-22 14:37:11 +05:00
e16d6fa878 Disabling setting default sort column on windows until it will
be fixed in go-gtk (https://github.com/mattn/go-gtk/issues/291).
2016-11-22 14:25:16 +05:00
89298d894b Hello, 0.1.0-beta5! 2016-11-22 12:02:12 +05:00
88b9b31f6a Updated README about required Go version. 2016-11-22 11:56:48 +05:00
1fe49871f1 Proper sorting by server name. 2016-11-22 11:53:54 +05:00
4f5bf90dbe Set 4.3.1 as default version in profiles dialog. 2016-11-22 11:38:48 +05:00
25bebf87df Re-enabled sorting for servers lists and hide offline checkboxes default value.
Re-enabled sorting for servers lists, which forces to use devel
version of Go. 1.7.3 have problems with GC and URTrator will
segfault.

Hide offline checkboxes for all servers and favorites now
checked by default.
2016-11-22 11:36:17 +05:00
c4ed421106 Temporary disable sorting in servers list until fixed in go-gtk. 2016-11-22 10:51:48 +05:00
0c0fcd5b24 First "sort by server name" implementation and button name fix.
First implementation of "Sort by server name" algo. Shitty, kinda
unreliable, but better than GTK's default.

Added Colorizer.Clear() func, which clears passed data from
colorcodes.

Fixed name on "Add to favorites" button.

Still cannot be successfully launched until some race conditions
will be fixed in go-gtk.
2016-11-22 09:48:19 +05:00
4d466a9d2b Servers sorting by ping and players count.
For now only on "Servers" tab, and REQUIRES custom go-gtk build
(see https://github.com/mattn/go-gtk/issues/290#issuecomment-262127956)
2016-11-22 07:36:27 +05:00
2cdee94efe Clipboard monitoring is here, so updating README. 2016-11-22 05:42:15 +05:00
9 changed files with 389 additions and 94 deletions

View File

@@ -2,6 +2,8 @@
[![Join the chat at https://gitter.im/urtrator/Lobby](https://badges.gitter.im/urtrator/Lobby.svg)](https://gitter.im/urtrator/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Chat on Matrix: #gitter_urtrator=2Flobby:matrix.org (Gitter bridge).
![Main Window](/doc/screenshots/0.1-main_window.png)
URTrator is a desktop application that should (eventually) replace
@@ -25,6 +27,7 @@ the game.
* Favorites servers.
* Updating single server.
* Showing information about servers (like in UrT Connector).
* Clipboard monitoring.
Planning:
@@ -35,11 +38,15 @@ Planning:
* All kinds of notifications.
* Extended profile editor, so every profile could have own configuration
files, etc.
* Clipboard monitoring.
* ...maybe more :)
# Installation
## Precautions
Due to Go's GC bugs, it is required to use devel version of Go
compiler!
## Release
You don't need to install anything, thanks to Go's.

View File

@@ -21,8 +21,28 @@ type Colorizer struct {
colors map[string]string
}
func (c *Colorizer) ClearFromMarkup(data string) string {
var result string = ""
data = html.EscapeString(data)
data_splitted := strings.Split(data, ">")
if len(data_splitted) > 1 {
for item := range data_splitted {
if len(data_splitted[item]) > 0 {
result += strings.Split(data_splitted[item], "<")[0]
}
}
} else {
result = data_splitted[0]
}
return result
}
func (c *Colorizer) Fix(data string) string {
result := ""
var result string = ""
data = html.EscapeString(data)

View File

@@ -10,5 +10,5 @@
package common
const (
URTRATOR_VERSION = "0.1-beta4"
URTRATOR_VERSION = "0.1.0"
)

View File

@@ -34,7 +34,7 @@ type Pooler struct {
func (p *Pooler) Initialize() {
fmt.Println("Initializing requester goroutine pooler...")
// ToDo: figure out how to make this work nice.
p.maxrequests = 100
p.maxrequests = 200
_ = runtime.GOMAXPROCS(runtime.NumCPU() * 4)
p.pp = "\377\377\377\377"
fmt.Println("Pooler initialized")
@@ -238,7 +238,9 @@ func (p *Pooler) UpdateSpecificServer(server *datamodels.Server) error {
if len(players) == 1 && len(players[0]) > 255 {
server.Players = "0"
} else {
server.Players = strconv.Itoa(len(players))
// Looks like we have last element to be empty, due to
// strings.Split() call before.
server.Players = strconv.Itoa(len(players) - 1)
}
server.PlayersInfo = strings.Join(received_lines[2:], "\\")
}

View File

@@ -13,6 +13,7 @@ import (
// stdlib
"fmt"
"runtime"
"sort"
"strconv"
"strings"
@@ -59,8 +60,12 @@ type MainWindow struct {
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
// 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
// Game launch button.
launch_button *gtk.Button
// Server's information.
@@ -127,8 +132,14 @@ type MainWindow struct {
// 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
}
func (m *MainWindow) addToFavorites() {
@@ -310,6 +321,18 @@ func (m *MainWindow) hideOfflineAllServers() {
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() {
@@ -322,6 +345,18 @@ func (m *MainWindow) hideOfflineFavoriteServers() {
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 {
@@ -343,6 +378,14 @@ func (m *MainWindow) loadAllServers(data map[string]string) {
continue
}
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
}
if !server.AllServersIterInList && server.AllServersIterSet {
m.all_servers_store.Append(iter)
server.AllServersIterInList = true
@@ -395,6 +438,14 @@ func (m *MainWindow) loadFavoriteServers(data map[string]string) {
continue
}
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
}
// 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 {
@@ -453,10 +504,40 @@ func (m *MainWindow) loadProfiles(data map[string]string) {
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, "Servers") {
m.fav_servers.Emit("cursor-changed")
} else if strings.Contains(current_tab, "Favorites") {
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": "Servers updated."})
// 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, "Servers") {
m.all_servers.Emit("cursor-changed")
} else if strings.Contains(current_tab, "Favorites") {
m.fav_servers.Emit("cursor-changed")
}
}
func (m *MainWindow) setQuickConnectDetails(data map[string]string) {
@@ -487,14 +568,17 @@ func (m *MainWindow) showHide() {
}
}
func (m *MainWindow) showServerInformation() {
fmt.Println("Showing server's information...")
}
func (m *MainWindow) showShortServerInformation() {
fmt.Println("Server selection changed, updating server's information widget...")
m.server_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, "Servers") {
current_tab = "Favorites"
} else if strings.Contains(current_tab, "Favorites") {
current_tab = "Servers"
}
}
srv_address := m.getIpFromServersList(current_tab)
// Getting server information from cache.
@@ -567,12 +651,22 @@ func (m *MainWindow) showShortServerInformation() {
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, "<markup><span font_weight=\"bold\">PLAYERS</span></markup>")
for _, value := range parsed_players_info {
// 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(value["nick"])
nick := ctx.Colorizer.Fix(parsed_players_info[players_map_keys[k]]["nick"])
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, nick)
m.server_info_store.SetValue(iter, 1, "(frags: " + value["frags"] + " | ping: " + value["ping"] + ")")
m.server_info_store.SetValue(iter, 1, "(frags: " + parsed_players_info[players_map_keys[k]]["frags"] + " | ping: " + parsed_players_info[players_map_keys[k]]["ping"] + ")")
}
// Just a separator.
@@ -584,11 +678,19 @@ func (m *MainWindow) showShortServerInformation() {
m.server_info_store.Append(iter)
m.server_info_store.SetValue(iter, 0, "<markup><span font_weight=\"bold\">OTHER PARAMETERS</span></markup>")
for key, value := range parsed_general_data {
// 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, key)
m.server_info_store.SetValue(iter, 1, value)
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]])
}
}
}
@@ -605,6 +707,7 @@ func (m *MainWindow) unlockInterface() {
}
func (m *MainWindow) updateOneServer() {
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "<markup><span foreground=\"red\" font_weight=\"bold\">Updating selected server...</span></markup>"})
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
srv_address := m.getIpFromServersList(current_tab)

View File

@@ -130,7 +130,7 @@ func (m *MainWindow) Initialize() {
m.vbox.PackStart(profile_and_launch_hbox, false, true, 5)
// Separator
sep := gtk.NewHSeparator()
sep := gtk.NewHBox(false, 0)
profile_and_launch_hbox.PackStart(sep, true, true, 5)
// Profile selection.
@@ -149,7 +149,7 @@ func (m *MainWindow) Initialize() {
m.launch_button = gtk.NewButtonWithLabel("Launch!")
m.launch_button.SetTooltipText("Launch Urban Terror")
m.launch_button.Clicked(m.launchGame)
launch_button_image := gtk.NewImageFromPixbuf(logo.ScaleSimple(32, 32, gdkpixbuf.INTERP_NEAREST))
launch_button_image := gtk.NewImageFromPixbuf(logo.ScaleSimple(24, 24, gdkpixbuf.INTERP_HYPER))
m.launch_button.SetImage(launch_button_image)
profile_and_launch_hbox.PackStart(m.launch_button, false, true, 5)
@@ -165,6 +165,9 @@ func (m *MainWindow) Initialize() {
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
ctx.Eventer.LaunchEvent("setToolbarLabelText", map[string]string{"text": "URTrator is ready."})
// Set flag that shows to other parts that we're initialized.
m.initialized = true
gtk.Main()
}
@@ -250,11 +253,6 @@ func (m *MainWindow) initializeSidebar() {
si_scroll.Add(m.server_info)
// Button to view additional server info.
additional_srv_info_button := gtk.NewButtonWithLabel("Additional information")
additional_srv_info_button.Clicked(m.showServerInformation)
si_vbox.PackStart(additional_srv_info_button, false, true, 5)
// Quick connect frame.
quick_connect_frame := gtk.NewFrame("Quick connect")
sidebar_vbox.PackStart(quick_connect_frame, false, true, 5)
@@ -296,6 +294,9 @@ func (m *MainWindow) initializeSidebar() {
// Initializes internal storages.
func (m *MainWindow) initializeStorages() {
// Application isn't initialized.
m.initialized = false
m.use_other_servers_tab = false
// Gamemodes.
m.gamemodes = make(map[string]string)
m.gamemodes = map[string]string{
@@ -384,6 +385,7 @@ func (m *MainWindow) initializeStorages() {
func (m *MainWindow) InitializeTabs() {
// Create tabs widget.
m.tab_widget = gtk.NewNotebook()
m.tab_widget.Connect("switch-page", m.tabChanged)
tab_allsrv_hbox := gtk.NewHBox(false, 0)
swin1 := gtk.NewScrolledWindow(nil, nil)
@@ -439,9 +441,15 @@ func (m *MainWindow) InitializeTabs() {
// Sorting.
// By default we are sorting by server name.
// ToDo: remembering it to configuration storage.
m.all_servers_store_sortable.SetSortColumnId(m.column_pos["Servers"]["Name"], gtk.SORT_ASCENDING)
// Sorting functions.
// Race conditions and GC crazyness appears when activated, so for
// now commenting it out.
m.all_servers_store_sortable.SetSortFunc(m.column_pos["Servers"]["Name"], m.sortServersByName)
m.all_servers_store_sortable.SetSortFunc(m.column_pos["Servers"]["Players"], m.sortServersByPlayers)
m.all_servers_store_sortable.SetSortFunc(m.column_pos["Servers"]["Ping"], m.sortServersByPing)
// Selection changed signal, which will update server's short info pane.
m.all_servers.Connect("cursor-changed", m.showShortServerInformation)
@@ -454,8 +462,30 @@ func (m *MainWindow) InitializeTabs() {
m.all_servers_hide_offline.SetTooltipText("Hide offline servers on Servers tab")
tab_all_srv_ctl_vbox.PackStart(m.all_servers_hide_offline, false, true, 5)
m.all_servers_hide_offline.Clicked(m.hideOfflineAllServers)
if ctx.Cfg.Cfg["/serverslist/all_servers/hide_offline"] == "1" {
// Restore value of hide offline servers checkbox.
// Set to checked for new installations.
all_servers_hide_offline_cb_val, ok := ctx.Cfg.Cfg["/serverslist/all_servers/hide_offline"]
if !ok {
m.all_servers_hide_offline.SetActive(true)
} else {
if all_servers_hide_offline_cb_val == "1" {
m.all_servers_hide_offline.SetActive(true)
}
}
// Checkbox for hiding passworded servers.
m.all_servers_hide_private = gtk.NewCheckButtonWithLabel("Hide private servers")
m.all_servers_hide_private.SetTooltipText("Hide servers which requires password to enter")
tab_all_srv_ctl_vbox.PackStart(m.all_servers_hide_private, false, true, 5)
m.all_servers_hide_private.Clicked(m.hidePrivateAllServers)
// Restore checkbox value.
all_servers_hide_private_cb_val, ok := ctx.Cfg.Cfg["/serverslist/all_servers/hide_private"]
if !ok {
m.all_servers_hide_private.SetActive(true)
} else {
if all_servers_hide_private_cb_val == "1" {
m.all_servers_hide_private.SetActive(true)
}
}
// Final separator.
@@ -493,7 +523,11 @@ func (m *MainWindow) InitializeTabs() {
width_int, _ := strconv.Atoi(width)
col := gtk.NewTreeViewColumnWithAttributes(name, gtk.NewCellRendererText(), "markup", position_int)
col.SetSortColumnId(position_int)
// For some reason this cause panic on Windows, so disabling
// default sorting here.
if runtime.GOOS != "windows" {
col.SetSortColumnId(position_int)
}
col.SetReorderable(true)
col.SetResizable(true)
// GtkTreeViewColumn.SetFixedWidth() accepts only positive integers.
@@ -524,8 +558,30 @@ func (m *MainWindow) InitializeTabs() {
m.fav_servers_hide_offline.SetTooltipText("Hide offline servers on Favorites tab")
tab_fav_srv_ctl_vbox.PackStart(m.fav_servers_hide_offline, false, true, 5)
m.fav_servers_hide_offline.Clicked(m.hideOfflineFavoriteServers)
if ctx.Cfg.Cfg["/serverslist/favorite/hide_offline"] == "1" {
// Restore value of hide offline servers checkbox.
// Set to checked for new installations.
favorite_servers_hide_offline_cb_val, ok := ctx.Cfg.Cfg["/serverslist/favorite/hide_offline"]
if !ok {
m.fav_servers_hide_offline.SetActive(true)
} else {
if favorite_servers_hide_offline_cb_val == "1" {
m.fav_servers_hide_offline.SetActive(true)
}
}
// Checkbox for hiding passworded servers.
m.fav_servers_hide_private = gtk.NewCheckButtonWithLabel("Hide private servers")
m.fav_servers_hide_private.SetTooltipText("Hide servers which requires password to enter")
tab_fav_srv_ctl_vbox.PackStart(m.fav_servers_hide_private, false, true, 5)
m.fav_servers_hide_private.Clicked(m.hidePrivateFavoriteServers)
// Restore checkbox value.
fav_servers_hide_private_cb_val, ok := ctx.Cfg.Cfg["/serverslist/favorite/hide_private"]
if !ok {
m.fav_servers_hide_private.SetActive(true)
} else {
if fav_servers_hide_private_cb_val == "1" {
m.fav_servers_hide_private.SetActive(true)
}
}
// Final separator.
@@ -548,7 +604,7 @@ func (m *MainWindow) InitializeToolbar() {
button_update_all_servers_icon_pixbuf.Write(button_update_all_servers_icon_bytes)
button_update_all_servers_icon := gtk.NewImageFromPixbuf(button_update_all_servers_icon_pixbuf.GetPixbuf())
button_update_all_servers := gtk.NewToolButton(button_update_all_servers_icon, "Update all servers")
button_update_all_servers.SetTooltipText("Update all servers in all tabs")
button_update_all_servers.SetTooltipText("Update all servers in currently selected tab")
button_update_all_servers.OnClicked(m.UpdateServers)
m.toolbar.Insert(button_update_all_servers, 0)
@@ -572,7 +628,7 @@ func (m *MainWindow) InitializeToolbar() {
fav_button_icon_pixbuf.SetSize(24, 24)
fav_button_icon_pixbuf.Write(fav_button_icon_bytes)
fav_button_icon := gtk.NewImageFromPixbuf(fav_button_icon_pixbuf.GetPixbuf())
fav_button := gtk.NewToolButton(fav_button_icon, "Update all servers")
fav_button := gtk.NewToolButton(fav_button_icon, "Add to favorites")
fav_button.SetTooltipText("Add selected server to favorites")
fav_button.OnClicked(m.addToFavorites)
m.toolbar.Insert(fav_button, 3)

View File

@@ -0,0 +1,96 @@
package ui
import (
// stdlib
"strconv"
"strings"
// 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
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
if current_tab == "Servers" {
model.GetValue(a, m.column_pos["Servers"]["Name"], &name1_raw)
model.GetValue(b, m.column_pos["Servers"]["Name"], &name2_raw)
} else if current_tab == "Favorites" {
model.GetValue(a, m.column_pos["Favorites"]["Name"], &name1_raw)
model.GetValue(b, m.column_pos["Favorites"]["Name"], &name2_raw)
} else {
return 0
}
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
}
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
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
if current_tab == "Servers" {
model.GetValue(a, m.column_pos["Servers"]["Players"], &players1_raw)
model.GetValue(b, m.column_pos["Servers"]["Players"], &players2_raw)
} else if current_tab == "Favorites" {
model.GetValue(a, m.column_pos["Favorites"]["Players"], &players1_raw)
model.GetValue(b, m.column_pos["Favorites"]["Players"], &players2_raw)
} else {
return 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
}
}
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
current_tab := m.tab_widget.GetTabLabelText(m.tab_widget.GetNthPage(m.tab_widget.GetCurrentPage()))
if current_tab == "Servers" {
model.GetValue(a, m.column_pos["Servers"]["Ping"], &ping1_raw)
model.GetValue(b, m.column_pos["Servers"]["Ping"], &ping2_raw)
} else if current_tab == "Favorites" {
model.GetValue(a, m.column_pos["Favorites"]["Ping"], &ping1_raw)
model.GetValue(b, m.column_pos["Favorites"]["Ping"], &ping2_raw)
} else {
return 0
}
ping1, _ := strconv.Atoi(ping1_raw.GetString())
ping2, _ := strconv.Atoi(ping2_raw.GetString())
if ping1 < ping2 {
return 1
} else {
return -1
}
return -1
}

View File

@@ -146,15 +146,33 @@ func (o *OptionsDialog) initializeAppearanceTab() {
func (o *OptionsDialog) initializeGeneralTab() {
general_vbox := gtk.NewVBox(false, 0)
general_table := gtk.NewTable(2, 2, false)
// Tray icon checkbox.
o.show_tray_icon = gtk.NewCheckButtonWithLabel("Show tray icon?")
show_tray_icon_label := gtk.NewLabel("Show icon in tray")
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("Show icon in tray")
general_vbox.PackStart(o.show_tray_icon, false, true, 5)
general_table.Attach(o.show_tray_icon, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
// Autoupdate checkbox.
o.autoupdate = gtk.NewCheckButtonWithLabel("Automatically update URTrator?")
o.autoupdate.SetTooltipText("Should URTrator check for updates and update itself? Not working now.")
general_vbox.PackStart(o.autoupdate, false, true, 5)
autoupdate_tooltip := "Should URTrator check for updates and update itself? Not working now."
autoupdate_label := gtk.NewLabel("Automatically update URTrator?")
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.FILL, 5, 5)
// Vertical separator.
sep := gtk.NewVBox(false, 0)
general_vbox.PackStart(general_table, false, true, 0)
general_vbox.PackStart(sep, false, true, 0)
o.tab_widget.AppendPage(general_vbox, gtk.NewLabel("General"))
}
@@ -176,7 +194,7 @@ func (o *OptionsDialog) initializeTabs() {
// Buttons for saving and discarding changes.
buttons_hbox := gtk.NewHBox(false, 0)
sep := gtk.NewHSeparator()
sep := gtk.NewHBox(false, 0)
cancel_button := gtk.NewButtonWithLabel("Cancel")
cancel_button.Clicked(o.closeOptionsDialogByCancel)
@@ -195,7 +213,7 @@ func (o *OptionsDialog) initializeTabs() {
}
func (o *OptionsDialog) initializeUrtTab() {
urt_hbox := gtk.NewHBox(false, 0)
urt_hbox := gtk.NewHBox(false, 5)
// Profiles list.
o.profiles_list = gtk.NewTreeView()
@@ -205,17 +223,13 @@ func (o *OptionsDialog) initializeUrtTab() {
o.profiles_list.AppendColumn(gtk.NewTreeViewColumnWithAttributes("Profile name", gtk.NewCellRendererText(), "text", 0))
o.profiles_list.AppendColumn(gtk.NewTreeViewColumnWithAttributes("Urban Terror version", gtk.NewCellRendererText(), "text", 1))
//crt := gtk.NewCellRendererToggle()
//second_x_column := gtk.NewTreeViewColumnWithAttributes("Second X session", crt, "bool", 2)
//o.profiles_list.AppendColumn(second_x_column)
// Profiles list buttons.
urt_profiles_buttons_vbox := gtk.NewVBox(false, 0)
button_add := gtk.NewButtonWithLabel("Add")
button_add.SetTooltipText("Add new profile")
button_add.Clicked(o.addProfile)
urt_profiles_buttons_vbox.PackStart(button_add, false, true, 5)
urt_profiles_buttons_vbox.PackStart(button_add, false, true, 0)
button_edit := gtk.NewButtonWithLabel("Edit")
button_edit.SetTooltipText("Edit selected profile. Do nothing if no profile was selected.")
@@ -223,13 +237,13 @@ func (o *OptionsDialog) initializeUrtTab() {
urt_profiles_buttons_vbox.PackStart(button_edit, false, true, 5)
// Spacer for profiles list buttons.
sep := gtk.NewVSeparator()
sep := gtk.NewVBox(false, 0)
urt_profiles_buttons_vbox.PackStart(sep, true, true, 5)
button_delete := gtk.NewButtonWithLabel("Delete")
button_delete.SetTooltipText("Delete selected profile. Do nothing if no profile was selected.")
button_delete.Clicked(o.deleteProfile)
urt_profiles_buttons_vbox.PackStart(button_delete, false, true, 5)
urt_profiles_buttons_vbox.PackStart(button_delete, false, true, 0)
urt_hbox.Add(urt_profiles_buttons_vbox)

View File

@@ -27,8 +27,8 @@ import (
type OptionsProfile struct {
// Window.
window *gtk.Window
// Main Vertical Box.
vbox *gtk.VBox
// Main table.
table *gtk.Table
// Profile name.
profile_name *gtk.Entry
// Binary path.
@@ -148,90 +148,85 @@ func (op *OptionsProfile) Initialize(update bool) {
op.window.SetPosition(gtk.WIN_POS_CENTER)
op.window.SetIcon(logo)
op.vbox = gtk.NewVBox(false, 0)
op.table = gtk.NewTable(6, 2, false)
op.table.SetRowSpacings(2)
// Profile name.
profile_name_tooltip := "This how you will see profile on profiles lists."
pn_hbox := gtk.NewHBox(false, 0)
pn_label := gtk.NewLabel("Profile name:")
pn_label.SetTooltipText(profile_name_tooltip)
profile_name_sep := gtk.NewHSeparator()
profile_name_sep.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)
pn_hbox.PackStart(pn_label, false, true, 5)
pn_hbox.PackStart(profile_name_sep, true, true, 5)
pn_hbox.PackStart(op.profile_name, true, true, 5)
op.vbox.PackStart(pn_hbox, false, true, 5)
op.table.Attach(op.profile_name, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
// Urban Terror version.
urt_version_tooltip := "Urban Terror version for which this profile applies."
urt_version_hbox := gtk.NewHBox(false, 0)
urt_version_label := gtk.NewLabel("Urban Terror version:")
urt_version_label.SetTooltipText(urt_version_tooltip)
urt_version_sep := gtk.NewHSeparator()
urt_version_sep.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.0")
op.urt_version_combo.AppendText("4.3.1")
op.urt_version_combo.SetActive(1)
urt_version_hbox.PackStart(urt_version_label, false, true, 5)
urt_version_hbox.PackStart(urt_version_sep, true, true, 5)
urt_version_hbox.PackStart(op.urt_version_combo, true, true, 5)
op.vbox.PackStart(urt_version_hbox, false, true, 5)
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 := "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"
binpath_hbox := gtk.NewHBox(false, 0)
binpath_label := gtk.NewLabel("Urban Terror binary:")
binpath_label.SetTooltipText(select_binary_tooltip)
binpath_sep := gtk.NewHSeparator()
binpath_sep.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("Browse")
button_select_binary.SetTooltipText(select_binary_tooltip)
button_select_binary.Clicked(op.browseForBinary)
binpath_hbox.PackStart(binpath_label, false, true, 5)
binpath_hbox.PackStart(binpath_sep, true, true, 5)
binpath_hbox.PackStart(op.binary_path, true, true, 5)
binpath_hbox.PackStart(button_select_binary, false, true, 5)
op.vbox.PackStart(binpath_hbox, false, true, 5)
op.table.Attach(binpath_hbox, 1, 2, 2, 3, gtk.FILL, gtk.FILL, 0, 0)
// Should we use additional X session?
another_x_tooltip := "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."
op.another_x_session = gtk.NewCheckButtonWithLabel("Start Urban Terror in another X session?")
another_x_label := gtk.NewLabel("Start Urban Terror in another X session?")
another_x_label.SetTooltipText(another_x_tooltip)
another_x_label.SetAlignment(0, 0)
op.table.Attach(another_x_label, 0, 1, 3, 4, gtk.FILL, gtk.SHRINK, 5, 5)
op.another_x_session = gtk.NewCheckButtonWithLabel("")
op.another_x_session.SetTooltipText(another_x_tooltip)
op.vbox.PackStart(op.another_x_session, false, true, 5)
// macOS can't do that :).
// 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, 3, 4, gtk.FILL, gtk.FILL, 5, 5)
// Additional game parameters.
params_tooltip := "Additional parameters that will be passed to Urban Terror executable."
params_hbox := gtk.NewHBox(false, 0)
params_label := gtk.NewLabel("Additional parameters:")
params_label.SetTooltipText(params_tooltip)
params_sep := gtk.NewHSeparator()
params_sep.SetTooltipText(params_tooltip)
params_label.SetAlignment(0, 0)
op.table.Attach(params_label, 0, 1, 4, 5, gtk.FILL, gtk.SHRINK, 5, 5)
op.additional_parameters = gtk.NewEntry()
op.additional_parameters.SetTooltipText(params_tooltip)
params_hbox.PackStart(params_label, false, true, 5)
params_hbox.PackStart(params_sep, true, true, 5)
params_hbox.PackStart(op.additional_parameters, true, true, 5)
op.vbox.PackStart(params_hbox, false, true, 5)
op.table.Attach(op.additional_parameters, 1, 2, 4, 5, gtk.FILL, gtk.FILL, 5, 5)
// Vertical separator.
vert_sep := gtk.NewVSeparator()
op.vbox.PackStart(vert_sep, true, true, 5)
// Invisible thing.
inv_label := gtk.NewLabel("")
op.table.Attach(inv_label, 1, 2, 5, 6, gtk.EXPAND, gtk.FILL, 5, 5)
// The buttons.
buttons_box := gtk.NewHBox(false, 0)
buttons_sep := gtk.NewHSeparator()
buttons_sep := gtk.NewHBox(false, 0)
cancel_button := gtk.NewButtonWithLabel("Cancel")
cancel_button.SetTooltipText("Close without saving")
@@ -251,9 +246,14 @@ func (op *OptionsProfile) Initialize(update bool) {
add_button.Clicked(op.saveProfile)
buttons_box.PackStart(add_button, false, true, 5)
op.vbox.PackStart(buttons_box, false, true, 5)
vert_sep_box := gtk.NewVBox(false, 0)
op.window.Add(op.vbox)
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()
}
@@ -262,26 +262,23 @@ func (op *OptionsProfile) InitializeUpdate(profile_name string) {
op.Initialize(true)
// Get profile data.
profile := []datamodels.Profile{}
err := ctx.Database.Db.Select(&profile, ctx.Database.Db.Rebind("SELECT * FROM urt_profiles WHERE name=?"), profile_name)
if err != nil {
fmt.Println(err.Error())
}
op.profile_name.SetText(profile[0].Name)
op.binary_path.SetText(profile[0].Binary)
op.additional_parameters.SetText(profile[0].Additional_params)
if profile[0].Second_x_session == "1" {
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.Second_x_session == "1" {
op.another_x_session.SetActive(true)
}
if profile[0].Version == "4.3.0" {
if profile.Version == "4.3.0" {
op.urt_version_combo.SetActive(1)
} else if profile.Version == "4.3.1" {
op.urt_version_combo.SetActive(2)
} else {
op.urt_version_combo.SetActive(0)
}
op.old_profile = &profile[0]
op.old_profile = profile
}