309 lines
9.7 KiB
Go
309 lines
9.7 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
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
|
|
// Local
|
|
"go.dev.pztrn.name/urtrator/cachemodels"
|
|
"go.dev.pztrn.name/urtrator/common"
|
|
"go.dev.pztrn.name/urtrator/datamodels"
|
|
|
|
// Other
|
|
"github.com/mattn/go-gtk/gdkpixbuf"
|
|
"github.com/mattn/go-gtk/gtk"
|
|
)
|
|
|
|
type FavoriteDialog struct {
|
|
// Widgets.
|
|
// Dialog's window.
|
|
window *gtk.Window
|
|
// Main vertical box.
|
|
vbox *gtk.VBox
|
|
// Server name.
|
|
server_name *gtk.Entry
|
|
// Server address.
|
|
server_address *gtk.Entry
|
|
// Server password
|
|
server_password *gtk.Entry
|
|
// Profile.
|
|
profile *gtk.ComboBoxText
|
|
|
|
// Flags.
|
|
// Is known server update performed?
|
|
update bool
|
|
|
|
// Data.
|
|
// Server's we're working with.
|
|
server *datamodels.Server
|
|
// Profiles count that was added to profiles combobox.
|
|
profiles int
|
|
}
|
|
|
|
func (f *FavoriteDialog) Close() {}
|
|
|
|
func (f *FavoriteDialog) closeByCancel() {
|
|
f.window.Destroy()
|
|
}
|
|
|
|
func (f *FavoriteDialog) fill() {
|
|
f.server_name.SetText(f.server.Name)
|
|
f.server_address.SetText(f.server.Ip + ":" + f.server.Port)
|
|
f.server_password.SetText(f.server.Password)
|
|
|
|
// Profiles.
|
|
// Remove old profiles.
|
|
if f.profiles > 0 {
|
|
for i := 0; i <= f.profiles; i++ {
|
|
f.profile.RemoveText(0)
|
|
}
|
|
}
|
|
|
|
profiles := []datamodels.Profile{}
|
|
err := ctx.Database.Db.Select(&profiles, "SELECT * FROM urt_profiles")
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
}
|
|
var idx_in_combobox int = 0
|
|
var idx_should_be_active int = 0
|
|
for p := range profiles {
|
|
if profiles[p].Version == f.server.Version {
|
|
f.profile.AppendText(profiles[p].Name)
|
|
idx_should_be_active = idx_in_combobox
|
|
idx_in_combobox += 1
|
|
f.profiles += 1
|
|
}
|
|
}
|
|
|
|
f.profile.SetActive(idx_should_be_active)
|
|
}
|
|
|
|
func (f *FavoriteDialog) InitializeNew() {
|
|
f.update = false
|
|
f.server = &datamodels.Server{}
|
|
f.profiles = 0
|
|
f.initializeWindow()
|
|
}
|
|
|
|
func (f *FavoriteDialog) InitializeUpdate(server *datamodels.Server) {
|
|
fmt.Println("Favorites updating...")
|
|
f.update = true
|
|
f.server = server
|
|
f.profiles = 0
|
|
f.initializeWindow()
|
|
f.fill()
|
|
}
|
|
|
|
func (f *FavoriteDialog) initializeWindow() {
|
|
f.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
|
|
if f.update {
|
|
f.window.SetTitle(ctx.Translator.Translate("URTrator - {{ action }} favorite server", map[string]string{"action": "Update"}))
|
|
} else {
|
|
f.window.SetTitle(ctx.Translator.Translate("URTrator - {{ action }} favorite server", map[string]string{"action": "Add"}))
|
|
}
|
|
f.window.Connect("destroy", f.Close)
|
|
f.window.SetPosition(gtk.WIN_POS_CENTER)
|
|
f.window.SetModal(true)
|
|
f.window.SetSizeRequest(400, 200)
|
|
f.window.SetResizable(false)
|
|
|
|
// Load program icon from base64.
|
|
icon_bytes, _ := base64.StdEncoding.DecodeString(common.Logo)
|
|
icon_pixbuf := gdkpixbuf.NewLoader()
|
|
icon_pixbuf.Write(icon_bytes)
|
|
logo = icon_pixbuf.GetPixbuf()
|
|
f.window.SetIcon(logo)
|
|
|
|
// Set some GTK options for this window.
|
|
gtk_opts_raw := gtk.SettingsGetDefault()
|
|
gtk_opts := gtk_opts_raw.ToGObject()
|
|
gtk_opts.Set("gtk-button-images", true)
|
|
|
|
f.vbox = gtk.NewVBox(false, 0)
|
|
|
|
table := gtk.NewTable(5, 2, false)
|
|
f.vbox.PackStart(table, true, true, 5)
|
|
|
|
// Server name.
|
|
srv_name_label := gtk.NewLabel(ctx.Translator.Translate("Server name:", nil))
|
|
srv_name_label.SetAlignment(0, 0)
|
|
table.Attach(srv_name_label, 0, 1, 0, 1, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
f.server_name = gtk.NewEntry()
|
|
table.Attach(f.server_name, 1, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Server address.
|
|
srv_addr_label := gtk.NewLabel(ctx.Translator.Translate("Server address:", nil))
|
|
srv_addr_label.SetAlignment(0, 0)
|
|
table.Attach(srv_addr_label, 0, 1, 1, 2, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
srv_addr_hbox := gtk.NewHBox(false, 0)
|
|
f.server_address = gtk.NewEntry()
|
|
srv_addr_hbox.PackStart(f.server_address, true, true, 0)
|
|
srv_addr_update_btn := gtk.NewButton()
|
|
srv_addr_update_btn.SetTooltipText(ctx.Translator.Translate("Update server information", nil))
|
|
srv_addr_update_btn_image := gtk.NewImageFromStock(gtk.STOCK_REDO, gtk.ICON_SIZE_SMALL_TOOLBAR)
|
|
srv_addr_update_btn.SetImage(srv_addr_update_btn_image)
|
|
srv_addr_update_btn.Clicked(f.updateServerInfo)
|
|
srv_addr_hbox.PackStart(srv_addr_update_btn, false, true, 5)
|
|
if f.update {
|
|
f.server_address.SetSensitive(false)
|
|
}
|
|
table.Attach(srv_addr_hbox, 1, 2, 1, 2, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Server password.
|
|
srv_pass_label := gtk.NewLabel(ctx.Translator.Translate("Password:", nil))
|
|
srv_pass_label.SetAlignment(0, 0)
|
|
table.Attach(srv_pass_label, 0, 1, 2, 3, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
f.server_password = gtk.NewEntry()
|
|
table.Attach(f.server_password, 1, 2, 2, 3, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Profile to use.
|
|
profile_label := gtk.NewLabel(ctx.Translator.Translate("Profile:", nil))
|
|
profile_label.SetAlignment(0, 0)
|
|
table.Attach(profile_label, 0, 1, 3, 4, gtk.FILL, gtk.SHRINK, 5, 5)
|
|
|
|
f.profile = gtk.NewComboBoxText()
|
|
table.Attach(f.profile, 1, 2, 3, 4, gtk.FILL, gtk.FILL, 5, 5)
|
|
|
|
// Invisible thing.
|
|
inv_label1 := gtk.NewLabel("")
|
|
table.Attach(inv_label1, 0, 1, 4, 5, gtk.EXPAND, gtk.FILL, 5, 5)
|
|
inv_label2 := gtk.NewLabel("")
|
|
table.Attach(inv_label2, 1, 2, 4, 5, gtk.EXPAND, gtk.FILL, 5, 5)
|
|
|
|
// Buttons hbox.
|
|
buttons_hbox := gtk.NewHBox(false, 0)
|
|
sep := gtk.NewHSeparator()
|
|
buttons_hbox.PackStart(sep, true, true, 5)
|
|
// OK-Cancel buttons.
|
|
cancel_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("Cancel", nil))
|
|
cancel_button.Clicked(f.closeByCancel)
|
|
buttons_hbox.PackStart(cancel_button, false, true, 5)
|
|
|
|
ok_button := gtk.NewButtonWithLabel(ctx.Translator.Translate("OK", nil))
|
|
ok_button.Clicked(f.saveFavorite)
|
|
buttons_hbox.PackStart(ok_button, false, true, 5)
|
|
|
|
f.vbox.PackStart(buttons_hbox, false, true, 5)
|
|
|
|
f.window.Add(f.vbox)
|
|
f.window.ShowAll()
|
|
}
|
|
|
|
func (f *FavoriteDialog) saveFavorite() error {
|
|
// Update server's information.
|
|
f.server.Name = f.server_name.GetText()
|
|
//ctx.Requester.Pooler.UpdateSpecificServer(f.server)
|
|
|
|
if len(f.server_address.GetText()) == 0 {
|
|
// Temporary disable all these modals on Linux.
|
|
// See https://github.com/mattn/go-gtk/issues/289.
|
|
if runtime.GOOS != "linux" {
|
|
mbox_string := ctx.Translator.Translate("Server address is empty.\n\nServers without address cannot be added.", nil)
|
|
m := gtk.NewMessageDialog(f.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
|
m.Response(func() {
|
|
m.Destroy()
|
|
})
|
|
m.Run()
|
|
}
|
|
return errors.New("No server address specified")
|
|
}
|
|
|
|
var port string = ""
|
|
if strings.Contains(f.server_address.GetText(), ":") {
|
|
port = strings.Split(f.server_address.GetText(), ":")[1]
|
|
} else {
|
|
port = "27960"
|
|
}
|
|
f.server.Ip = strings.Split(f.server_address.GetText(), ":")[0]
|
|
f.server.Port = port
|
|
|
|
if len(f.profile.GetActiveText()) == 0 {
|
|
// Temporary disable all these modals on Linux.
|
|
// See https://github.com/mattn/go-gtk/issues/289.
|
|
if runtime.GOOS != "linux" {
|
|
mbox_string := ctx.Translator.Translate("Profile wasn't selected.\n\nPlease, select valid profile for this server.\nIf you haven't add profiles yet - you can do it\nin options on \"Urban Terror\" tab.", nil)
|
|
m := gtk.NewMessageDialog(f.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, mbox_string)
|
|
m.Response(func() {
|
|
m.Destroy()
|
|
})
|
|
m.Run()
|
|
}
|
|
return errors.New("No game profile specified")
|
|
}
|
|
|
|
fmt.Println("Saving favorite server...")
|
|
fmt.Println(fmt.Sprintf("%+v", f.server))
|
|
|
|
key := strings.Split(f.server_address.GetText(), ":")[0] + ":" + port
|
|
|
|
// Check if server already in cache. This would replace data about it.
|
|
_, ok := ctx.Cache.Servers[key]
|
|
if !ok {
|
|
ctx.Cache.Servers[key] = &cachemodels.Server{}
|
|
ctx.Cache.Servers[key].Server = &datamodels.Server{}
|
|
}
|
|
|
|
ctx.Cache.Servers[key].Server.Ip = f.server.Ip
|
|
ctx.Cache.Servers[key].Server.Port = f.server.Port
|
|
ctx.Cache.Servers[key].Server.Name = f.server.Name
|
|
ctx.Cache.Servers[key].Server.Password = f.server_password.GetText()
|
|
ctx.Cache.Servers[key].Server.ProfileToUse = f.profile.GetActiveText()
|
|
ctx.Cache.Servers[key].Server.Favorite = "1"
|
|
ctx.Cache.Servers[key].Server.ExtendedConfig = f.server.ExtendedConfig
|
|
ctx.Cache.Servers[key].Server.PlayersInfo = f.server.PlayersInfo
|
|
|
|
ctx.Eventer.LaunchEvent("flushServers", map[string]string{})
|
|
ctx.Eventer.LaunchEvent("loadFavoriteServers", map[string]string{})
|
|
f.window.Destroy()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (f *FavoriteDialog) updateServerInfo() {
|
|
fmt.Println("Updating server information...")
|
|
var port string = ""
|
|
if strings.Contains(f.server_address.GetText(), ":") {
|
|
port = strings.Split(f.server_address.GetText(), ":")[1]
|
|
} else {
|
|
port = "27960"
|
|
}
|
|
f.server.Ip = strings.Split(f.server_address.GetText(), ":")[0]
|
|
f.server.Port = port
|
|
|
|
ctx.Requester.Pooler.UpdateSpecificServer(f.server)
|
|
|
|
f.fill()
|
|
}
|