feat: added versionning & About window
This commit is contained in:
@@ -74,8 +74,11 @@ const (
|
||||
keyListsRSTDigital = "lists.rst_digital"
|
||||
|
||||
keyCATEnabled = "cat.enabled"
|
||||
keyCATBackend = "cat.backend" // "omnirig" (only one for now)
|
||||
keyCATBackend = "cat.backend" // "omnirig" | "flex"
|
||||
keyCATOmniRigNum = "cat.omnirig.rig" // 1 or 2
|
||||
keyCATFlexHost = "cat.flex.host" // FlexRadio IP (native backend)
|
||||
keyCATFlexPort = "cat.flex.port" // FlexRadio TCP port (default 4992)
|
||||
keyCATFlexSpots = "cat.flex.spots" // push cluster spots to the panadapter
|
||||
keyCATPollMs = "cat.poll_ms"
|
||||
keyCATDelayMs = "cat.delay_ms" // pause between commands
|
||||
keyCATDigitalDefault = "cat.digital_default" // mode to use when CAT reports DATA
|
||||
@@ -225,8 +228,11 @@ type QSLDefaults struct {
|
||||
// individual key/value pairs to keep the settings table flat.
|
||||
type CATSettings struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Backend string `json:"backend"` // currently always "omnirig"
|
||||
Backend string `json:"backend"` // "omnirig" | "flex"
|
||||
OmniRigNum int `json:"omnirig_rig"` // 1 or 2 (OmniRig "Rig1"/"Rig2" slot)
|
||||
FlexHost string `json:"flex_host"` // FlexRadio IP (native backend)
|
||||
FlexPort int `json:"flex_port"` // FlexRadio TCP port (default 4992)
|
||||
FlexSpots bool `json:"flex_spots"` // push cluster spots to the panadapter
|
||||
PollMs int `json:"poll_ms"` // poll interval in ms (default 250)
|
||||
DelayMs int `json:"delay_ms"` // pause between commands (default 0)
|
||||
DigitalDefault string `json:"digital_default"` // when CAT says DATA, surface this mode (FT8/FT4/RTTY/…)
|
||||
@@ -372,6 +378,7 @@ type App struct {
|
||||
logDb *sql.DB // QSO logbook connection — MySQL when the shared backend is enabled, else == db (local SQLite)
|
||||
dbBackend string // "sqlite" | "mysql" — the logbook backend actually opened at startup
|
||||
dbBackendErr string // non-empty when a configured MySQL backend failed and we fell back to SQLite
|
||||
catFlexSpots bool // push cluster spots to the FlexRadio panadapter
|
||||
awardSnapMu sync.Mutex // guards the award QSO snapshot
|
||||
awardSnap []qso.QSO // light-scanned + enriched logbook snapshot reused across award computations
|
||||
awardSnapRev string // logbook revision the snapshot was built at ("" = none)
|
||||
@@ -668,6 +675,16 @@ func (a *App) startup(ctx context.Context) {
|
||||
if a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "cluster:spot", s)
|
||||
}
|
||||
// Mirror the spot onto the FlexRadio panadapter when enabled. The
|
||||
// Color is left to the backend default for now — status-based
|
||||
// colouring can be filled in here later (new entity / worked / …).
|
||||
if a.catFlexSpots && a.cat != nil {
|
||||
a.cat.SendSpot(cat.SpotInfo{
|
||||
FreqHz: s.FreqHz,
|
||||
Callsign: s.DXCall,
|
||||
Comment: s.Comment,
|
||||
})
|
||||
}
|
||||
},
|
||||
func() {
|
||||
if a.ctx != nil {
|
||||
@@ -3558,7 +3575,7 @@ func (a *App) GetCATSettings() (CATSettings, error) {
|
||||
if a.settings == nil {
|
||||
return CATSettings{Backend: "omnirig", OmniRigNum: 1, PollMs: 250}, fmt.Errorf("db not initialized")
|
||||
}
|
||||
m, err := a.settings.GetMany(a.ctx, keyCATEnabled, keyCATBackend, keyCATOmniRigNum, keyCATPollMs, keyCATDelayMs, keyCATDigitalDefault)
|
||||
m, err := a.settings.GetMany(a.ctx, keyCATEnabled, keyCATBackend, keyCATOmniRigNum, keyCATFlexHost, keyCATFlexPort, keyCATFlexSpots, keyCATPollMs, keyCATDelayMs, keyCATDigitalDefault)
|
||||
if err != nil {
|
||||
return CATSettings{}, err
|
||||
}
|
||||
@@ -3566,10 +3583,16 @@ func (a *App) GetCATSettings() (CATSettings, error) {
|
||||
Enabled: m[keyCATEnabled] == "1",
|
||||
Backend: m[keyCATBackend],
|
||||
OmniRigNum: 1,
|
||||
FlexHost: m[keyCATFlexHost],
|
||||
FlexPort: 4992,
|
||||
FlexSpots: m[keyCATFlexSpots] == "1",
|
||||
PollMs: 250,
|
||||
DelayMs: 0,
|
||||
DigitalDefault: m[keyCATDigitalDefault],
|
||||
}
|
||||
if n, _ := strconv.Atoi(m[keyCATFlexPort]); n > 0 && n <= 65535 {
|
||||
out.FlexPort = n
|
||||
}
|
||||
if out.Backend == "" {
|
||||
out.Backend = "omnirig"
|
||||
}
|
||||
@@ -3599,6 +3622,9 @@ func (a *App) SaveCATSettings(s CATSettings) error {
|
||||
if s.OmniRigNum != 1 && s.OmniRigNum != 2 {
|
||||
s.OmniRigNum = 1
|
||||
}
|
||||
if s.FlexPort <= 0 || s.FlexPort > 65535 {
|
||||
s.FlexPort = 4992
|
||||
}
|
||||
if s.PollMs < 50 || s.PollMs > 2000 {
|
||||
s.PollMs = 250
|
||||
}
|
||||
@@ -3609,6 +3635,10 @@ func (a *App) SaveCATSettings(s CATSettings) error {
|
||||
if s.Enabled {
|
||||
enabled = "1"
|
||||
}
|
||||
flexSpots := "0"
|
||||
if s.FlexSpots {
|
||||
flexSpots = "1"
|
||||
}
|
||||
if s.DigitalDefault == "" {
|
||||
s.DigitalDefault = "FT8"
|
||||
}
|
||||
@@ -3616,6 +3646,9 @@ func (a *App) SaveCATSettings(s CATSettings) error {
|
||||
keyCATEnabled: enabled,
|
||||
keyCATBackend: s.Backend,
|
||||
keyCATOmniRigNum: strconv.Itoa(s.OmniRigNum),
|
||||
keyCATFlexHost: strings.TrimSpace(s.FlexHost),
|
||||
keyCATFlexPort: strconv.Itoa(s.FlexPort),
|
||||
keyCATFlexSpots: flexSpots,
|
||||
keyCATPollMs: strconv.Itoa(s.PollMs),
|
||||
keyCATDelayMs: strconv.Itoa(s.DelayMs),
|
||||
keyCATDigitalDefault: strings.ToUpper(strings.TrimSpace(s.DigitalDefault)),
|
||||
@@ -6294,6 +6327,7 @@ func (a *App) reloadCAT() {
|
||||
}
|
||||
a.cat.SetPollInterval(time.Duration(s.PollMs) * time.Millisecond)
|
||||
a.cat.SetCommandDelay(time.Duration(s.DelayMs) * time.Millisecond)
|
||||
a.catFlexSpots = s.Enabled && s.Backend == "flex" && s.FlexSpots
|
||||
if !s.Enabled {
|
||||
a.cat.Stop()
|
||||
return
|
||||
@@ -6306,12 +6340,28 @@ func (a *App) reloadCAT() {
|
||||
// reloadCAT raised the existing instance's window to the front,
|
||||
// which is what Log4OM avoids by relying entirely on COM activation.
|
||||
a.cat.Start(cat.NewOmniRig(s.OmniRigNum))
|
||||
case "flex":
|
||||
// Native FlexRadio (SmartSDR) TCP API — no OmniRig needed.
|
||||
fb := cat.NewFlex(s.FlexHost, s.FlexPort, s.FlexSpots)
|
||||
// Clicking one of our spots on the panadapter fills the entry form.
|
||||
fb.OnSpotClick = func(call string, hz int64) {
|
||||
if a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "flex:spot_clicked", map[string]any{"call": call, "freq_hz": hz})
|
||||
}
|
||||
}
|
||||
a.cat.Start(fb)
|
||||
default:
|
||||
// Unknown backend → stop and emit a dummy state so the UI shows it.
|
||||
a.cat.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// DiscoverFlexRadios listens for FlexRadio discovery broadcasts on the LAN and
|
||||
// returns the radios found (for the CAT settings "auto-detect" button).
|
||||
func (a *App) DiscoverFlexRadios() ([]cat.FlexRadio, error) {
|
||||
return cat.DiscoverFlex(2500 * time.Millisecond)
|
||||
}
|
||||
|
||||
// ClearLookupCache empties the local callsign cache.
|
||||
func (a *App) ClearLookupCache() error {
|
||||
if a.cache == nil {
|
||||
|
||||
Reference in New Issue
Block a user