From d341df82fbc20fa2dc911097a9190defd5c3307f Mon Sep 17 00:00:00 2001 From: Florian Thienel Date: Mon, 23 Dec 2024 22:00:53 +0100 Subject: [PATCH 1/4] show a dialog before selecting the cabrillo file --- core/app/app.go | 44 ++++++++++++++++----------- core/export/cabrillo/cabrillo.go | 34 +++++++++++++++++++++ ui/app.go | 29 ++++++++++-------- ui/exportCabrilloDialog.go | 51 ++++++++++++++++++++++++++++++++ ui/exportCabrilloView.go | 4 +++ 5 files changed, 131 insertions(+), 31 deletions(-) create mode 100644 ui/exportCabrilloDialog.go create mode 100644 ui/exportCabrilloView.go diff --git a/core/app/app.go b/core/app/app.go index d0c2228..4b0fd23 100644 --- a/core/app/app.go +++ b/core/app/app.go @@ -70,22 +70,23 @@ type Controller struct { callHistoryFinder *callhistory.Finder hamDXMap *hamdxmap.HamDXMap - VFO *vfo.VFO - Logbook *logbook.Logbook - QSOList *logbook.QSOList - Entry *entry.Controller - Workmode *workmode.Controller - Radio *radio.Controller - Keyer *keyer.Keyer - Callinfo *callinfo.Callinfo - Score *score.Counter - Rate *rate.Counter - ServiceStatus *ServiceStatus - NewContest *newcontest.Controller - Settings *settings.Settings - Bandmap *bandmap.Bandmap - Clusters *cluster.Clusters - Parrot *parrot.Parrot + VFO *vfo.VFO + Logbook *logbook.Logbook + QSOList *logbook.QSOList + Entry *entry.Controller + Workmode *workmode.Controller + Radio *radio.Controller + Keyer *keyer.Keyer + Callinfo *callinfo.Callinfo + Score *score.Counter + Rate *rate.Counter + ServiceStatus *ServiceStatus + NewContestDialog *newcontest.Controller + ExportCabrilloDialog *cabrillo.Controller + Settings *settings.Settings + Bandmap *bandmap.Bandmap + Clusters *cluster.Clusters + Parrot *parrot.Parrot } // View defines the visual functionality of the main application window. @@ -146,7 +147,8 @@ func (c *Controller) Startup() { c.configuration.Contest(), ) c.callHistoryFinder.Notify(c.Settings) - c.NewContest = newcontest.NewController(c.Settings, c.configuration.LogDirectory()) + c.NewContestDialog = newcontest.NewController(c.Settings, c.configuration.LogDirectory()) + c.ExportCabrilloDialog = cabrillo.NewController() c.bandplan = bandplan.IARURegion1 // TODO: make the bandplan configurable c.dxccFinder = dxcc.New() @@ -396,7 +398,7 @@ func proposeFilename(contestName, callsign string) string { func (c *Controller) New() { var err error - newContest, ok := c.NewContest.Run() + newContest, ok := c.NewContestDialog.Run() if !ok { return } @@ -538,6 +540,12 @@ func (c *Controller) SaveAs() { } func (c *Controller) ExportCabrillo() { + var err error + ok := c.ExportCabrilloDialog.Run() + if !ok { + return + } + proposedName := c.proposeFilename() + ".cabrillo" filename, ok, err := c.view.SelectSaveFile("Export Cabrillo File", c.configuration.LogDirectory(), proposedName, "*.cabrillo") if !ok { diff --git a/core/export/cabrillo/cabrillo.go b/core/export/cabrillo/cabrillo.go index 7c1b077..6d5bb08 100644 --- a/core/export/cabrillo/cabrillo.go +++ b/core/export/cabrillo/cabrillo.go @@ -12,6 +12,40 @@ import ( "github.com/ftl/hellocontest/core" ) +type View interface { + Show() bool +} + +type Controller struct { + view View +} + +func NewController() *Controller { + result := &Controller{} + + return result +} + +func (c *Controller) SetView(view View) { + if view == nil { + panic("cabrillo.Controller.SetView must not be called with nil") + } + if c.view != nil { + panic("cabrillo.Controller.SetView was already called") + } + + c.view = view +} + +func (c *Controller) Run() bool { + accepted := c.view.Show() + if !accepted { + return false + } + + return accepted +} + // Export writes the given QSOs to the given writer in the Cabrillo format. // The header is very limited and needs to be completed manually after the log was written. func Export(w io.Writer, settings core.Settings, claimedScore int, qsos ...core.QSO) error { diff --git a/ui/app.go b/ui/app.go index e72c8eb..36ce772 100644 --- a/ui/app.go +++ b/ui/app.go @@ -42,17 +42,18 @@ type application struct { version string sponsors string - app *gtk.Application - builder *gtk.Builder - style *style.Style - windowGeometry *gmtry.Geometry - mainWindow *mainWindow - scoreWindow *scoreWindow - rateWindow *rateWindow - spotsWindow *spotsWindow - newContestDialog *newContestDialog - settingsDialog *settingsDialog - keyerSettingsDialog *keyerSettingsDialog + app *gtk.Application + builder *gtk.Builder + style *style.Style + windowGeometry *gmtry.Geometry + mainWindow *mainWindow + scoreWindow *scoreWindow + rateWindow *rateWindow + spotsWindow *spotsWindow + newContestDialog *newContestDialog + exportCabrilloDialog *exportCabrilloDialog + settingsDialog *settingsDialog + keyerSettingsDialog *keyerSettingsDialog controller *app.Controller } @@ -94,7 +95,8 @@ func (a *application) activate() { a.spotsWindow = setupSpotsWindow(a.windowGeometry, a.style, a.controller.Bandmap) a.settingsDialog = setupSettingsDialog(a.mainWindow.window, a.controller.Settings) a.keyerSettingsDialog = setupKeyerSettingsDialog(a.mainWindow.window, a.controller.Keyer) - a.newContestDialog = setupNewContestDialog(a.mainWindow.window, a.controller.NewContest) + a.newContestDialog = setupNewContestDialog(a.mainWindow.window, a.controller.NewContestDialog) + a.exportCabrilloDialog = setupExportCabrilloDialog(a.mainWindow.window, a.controller.ExportCabrillo) a.mainWindow.SetMainMenuController(a.controller) a.mainWindow.SetRadioMenuController(a.controller) @@ -123,7 +125,8 @@ func (a *application) activate() { a.controller.Bandmap.SetView(a.spotsWindow) a.controller.Settings.SetView(a.settingsDialog) a.controller.Settings.Notify(a.mainWindow) - a.controller.NewContest.SetView(a.newContestDialog) + a.controller.NewContestDialog.SetView(a.newContestDialog) + a.controller.ExportCabrilloDialog.SetView(a.exportCabrilloDialog) a.controller.Clusters.SetView(a.mainWindow) a.controller.Parrot.SetView(a.mainWindow) diff --git a/ui/exportCabrilloDialog.go b/ui/exportCabrilloDialog.go new file mode 100644 index 0000000..71ec162 --- /dev/null +++ b/ui/exportCabrilloDialog.go @@ -0,0 +1,51 @@ +package ui + +import ( + "github.com/gotk3/gotk3/gtk" +) + +type exportCabrilloDialog struct { + dialog *gtk.Dialog + parent gtk.IWidget +} + +func setupExportCabrilloDialog(parent gtk.IWidget, controller ExportCabrilloController) *exportCabrilloDialog { + result := &exportCabrilloDialog{ + parent: parent, + } + return result +} + +func (d *exportCabrilloDialog) onDestroy() { + d.dialog = nil +} + +func (d *exportCabrilloDialog) Show() bool { + label, _ := gtk.LabelNew("Export the log as Cabrillo format.") + + grid, _ := gtk.GridNew() + grid.SetOrientation(gtk.ORIENTATION_VERTICAL) + grid.Add(label) + + dialog, _ := gtk.DialogNew() + d.dialog = dialog + d.dialog.SetDefaultSize(400, 300) + d.dialog.SetTransientFor(nil) + d.dialog.SetPosition(gtk.WIN_POS_CENTER) + d.dialog.Connect("destroy", d.onDestroy) + d.dialog.SetTitle("Export Log as Cabrillo") + d.dialog.SetDefaultResponse(gtk.RESPONSE_OK) + d.dialog.SetModal(true) + contentArea, _ := d.dialog.GetContentArea() + contentArea.Add(grid) + d.dialog.AddButton("Export", gtk.RESPONSE_OK) + d.dialog.AddButton("Cancel", gtk.RESPONSE_CANCEL) + + d.dialog.ShowAll() + result := d.dialog.Run() == gtk.RESPONSE_OK + d.dialog.Close() + d.dialog.Destroy() + d.dialog = nil + + return result +} diff --git a/ui/exportCabrilloView.go b/ui/exportCabrilloView.go new file mode 100644 index 0000000..4c17faf --- /dev/null +++ b/ui/exportCabrilloView.go @@ -0,0 +1,4 @@ +package ui + +type ExportCabrilloController interface { +} From c997065e3d5d15b4ec8b6b7b649fd3d92d0d470d Mon Sep 17 00:00:00 2001 From: Florian Thienel Date: Tue, 24 Dec 2024 12:20:17 +0100 Subject: [PATCH 2/4] let the user choose to open the file after export Signed-off-by: Florian Thienel --- core/app/app.go | 53 +++++++++++++-------------- core/export/cabrillo/cabrillo.go | 35 +++++++++++++----- core/export/cabrillo/cabrillo_test.go | 45 +++++++++++++---------- go.mod | 2 +- go.sum | 4 +- ui/app.go | 8 ++-- ui/exportCabrilloDialog.go | 27 ++++++++++++-- ui/exportCabrilloView.go | 18 +++++++++ 8 files changed, 126 insertions(+), 66 deletions(-) diff --git a/core/app/app.go b/core/app/app.go index 4b0fd23..aca1e46 100644 --- a/core/app/app.go +++ b/core/app/app.go @@ -70,23 +70,23 @@ type Controller struct { callHistoryFinder *callhistory.Finder hamDXMap *hamdxmap.HamDXMap - VFO *vfo.VFO - Logbook *logbook.Logbook - QSOList *logbook.QSOList - Entry *entry.Controller - Workmode *workmode.Controller - Radio *radio.Controller - Keyer *keyer.Keyer - Callinfo *callinfo.Callinfo - Score *score.Counter - Rate *rate.Counter - ServiceStatus *ServiceStatus - NewContestDialog *newcontest.Controller - ExportCabrilloDialog *cabrillo.Controller - Settings *settings.Settings - Bandmap *bandmap.Bandmap - Clusters *cluster.Clusters - Parrot *parrot.Parrot + VFO *vfo.VFO + Logbook *logbook.Logbook + QSOList *logbook.QSOList + Entry *entry.Controller + Workmode *workmode.Controller + Radio *radio.Controller + Keyer *keyer.Keyer + Callinfo *callinfo.Callinfo + Score *score.Counter + Rate *rate.Counter + ServiceStatus *ServiceStatus + NewContestController *newcontest.Controller + ExportCabrilloController *cabrillo.Controller + Settings *settings.Settings + Bandmap *bandmap.Bandmap + Clusters *cluster.Clusters + Parrot *parrot.Parrot } // View defines the visual functionality of the main application window. @@ -147,8 +147,8 @@ func (c *Controller) Startup() { c.configuration.Contest(), ) c.callHistoryFinder.Notify(c.Settings) - c.NewContestDialog = newcontest.NewController(c.Settings, c.configuration.LogDirectory()) - c.ExportCabrilloDialog = cabrillo.NewController() + c.NewContestController = newcontest.NewController(c.Settings, c.configuration.LogDirectory()) + c.ExportCabrilloController = cabrillo.NewController() c.bandplan = bandplan.IARURegion1 // TODO: make the bandplan configurable c.dxccFinder = dxcc.New() @@ -398,7 +398,7 @@ func proposeFilename(contestName, callsign string) string { func (c *Controller) New() { var err error - newContest, ok := c.NewContestDialog.Run() + newContest, ok := c.NewContestController.Run() if !ok { return } @@ -541,7 +541,7 @@ func (c *Controller) SaveAs() { func (c *Controller) ExportCabrillo() { var err error - ok := c.ExportCabrilloDialog.Run() + export, openCabrilloFile, ok := c.ExportCabrilloController.Run(c.Settings, c.Score.Result(), c.QSOList.All()) if !ok { return } @@ -563,16 +563,15 @@ func (c *Controller) ExportCabrillo() { } defer file.Close() - err = cabrillo.Export( - file, - c.Settings, - c.Score.Result(), - c.QSOList.All()...) + err = cabrillo.Export(file, export) if err != nil { c.view.ShowErrorDialog("Cannot export Cabrillo to %s: %v", filename, err) return } - c.openWithExternalApplication(filename) + + if openCabrilloFile { + c.openWithExternalApplication(filename) + } } func (c *Controller) ExportADIF() { diff --git a/core/export/cabrillo/cabrillo.go b/core/export/cabrillo/cabrillo.go index 6d5bb08..36109c6 100644 --- a/core/export/cabrillo/cabrillo.go +++ b/core/export/cabrillo/cabrillo.go @@ -14,14 +14,20 @@ import ( type View interface { Show() bool + + SetOpenAfterExport(bool) } type Controller struct { view View + + openAfterExport bool } func NewController() *Controller { - result := &Controller{} + result := &Controller{ + openAfterExport: false, + } return result } @@ -37,22 +43,27 @@ func (c *Controller) SetView(view View) { c.view = view } -func (c *Controller) Run() bool { +func (c *Controller) Run(settings core.Settings, claimedScore int, qsos []core.QSO) (*cabrillo.Log, bool, bool) { + c.view.SetOpenAfterExport(c.openAfterExport) accepted := c.view.Show() if !accepted { - return false + return nil, false, false } - return accepted + export := createCabrilloLog(settings, claimedScore, qsos) + + return export, c.openAfterExport, true } -// Export writes the given QSOs to the given writer in the Cabrillo format. -// The header is very limited and needs to be completed manually after the log was written. -func Export(w io.Writer, settings core.Settings, claimedScore int, qsos ...core.QSO) error { +func (c *Controller) SetOpenAfterExport(open bool) { + c.openAfterExport = open +} + +func createCabrilloLog(settings core.Settings, claimedScore int, qsos []core.QSO) *cabrillo.Log { export := cabrillo.NewLog() export.Callsign = settings.Station().Callsign export.CreatedBy = "Hello Contest" - export.Contest = cabrillo.ContestIdentifier(settings.Contest().Name) + export.Contest = cabrillo.ContestIdentifier(settings.Contest().Definition.Identifier) export.Operators = []callsign.Callsign{settings.Station().Operator} export.GridLocator = settings.Station().Locator export.ClaimedScore = claimedScore @@ -70,9 +81,15 @@ func Export(w io.Writer, settings core.Settings, claimedScore int, qsos ...core. export.QSOData = qsoData export.IgnoredQSOs = ignoredQSOs + return export +} + +// Export writes the given QSOs to the given writer in the Cabrillo format. +// The header is very limited and needs to be completed manually after the log was written. +func Export(w io.Writer, export *cabrillo.Log) error { return cabrillo.WriteWithTags(w, export, false, false, cabrillo.CreatedByTag, cabrillo.ContestTag, cabrillo.CallsignTag, cabrillo.OperatorsTag, cabrillo.GridLocatorTag, cabrillo.ClaimedScoreTag, - cabrillo.Tag("SPECIFIC"), cabrillo.CategoryAssistedTag, cabrillo.CategoryBandTag, cabrillo.CategoryModeTag, + cabrillo.CategoryAssistedTag, cabrillo.CategoryBandTag, cabrillo.CategoryModeTag, cabrillo.CategoryOperatorTag, cabrillo.CategoryPowerTag, cabrillo.ClubTag, cabrillo.NameTag, cabrillo.EmailTag) } diff --git a/core/export/cabrillo/cabrillo_test.go b/core/export/cabrillo/cabrillo_test.go index 4431772..3333957 100644 --- a/core/export/cabrillo/cabrillo_test.go +++ b/core/export/cabrillo/cabrillo_test.go @@ -6,6 +6,7 @@ import ( "text/template" "time" + "github.com/ftl/conval" "github.com/ftl/hamradio/callsign" "github.com/ftl/hamradio/locator" "github.com/stretchr/testify/assert" @@ -68,9 +69,10 @@ func TestQsoLine(t *testing.T) { func TestExport(t *testing.T) { buffer := bytes.NewBuffer([]byte{}) settings := &testSettings{ - stationCallsign: "AA1ZZZ", - stationOperator: "AA2ZZZ", - stationLocator: "AA00AA", + stationCallsign: "AA1ZZZ", + stationOperator: "AA2ZZZ", + stationLocator: "AA00AA", + contestIdentifier: "HELLO-CONTEST-CABRILLO-TEST", } theirCall, _ := callsign.Parse("S50A") qso := core.QSO{ @@ -88,33 +90,34 @@ func TestExport(t *testing.T) { expected := `START-OF-LOG: 3.0 CREATED-BY: Hello Contest -CONTEST: +CONTEST: HELLO-CONTEST-CABRILLO-TEST CALLSIGN: AA1ZZZ OPERATORS: AA2ZZZ GRID-LOCATOR: AA00aa CLAIMED-SCORE: 123 -SPECIFIC: -CATEGORY-ASSISTED: -CATEGORY-BAND: -CATEGORY-MODE: -CATEGORY-OPERATOR: -CATEGORY-POWER: -CLUB: -NAME: -EMAIL: +CATEGORY-ASSISTED: +CATEGORY-BAND: +CATEGORY-MODE: +CATEGORY-OPERATOR: +CATEGORY-POWER: +CLUB: +NAME: +EMAIL: QSO: 7000 CW 2009-05-30 0002 AA1ZZZ 599 001 ABC S50A 589 004 DEF -END-OF-LOG: +END-OF-LOG: ` - Export(buffer, settings, 123, qso) + export := createCabrilloLog(settings, 123, []core.QSO{qso}) + Export(buffer, export) assert.Equal(t, expected, buffer.String()) } type testSettings struct { - stationCallsign string - stationOperator string - stationLocator string + stationCallsign string + stationOperator string + stationLocator string + contestIdentifier string } func (s *testSettings) Station() core.Station { @@ -127,5 +130,9 @@ func (s *testSettings) Station() core.Station { } func (s *testSettings) Contest() core.Contest { - return core.Contest{} + return core.Contest{ + Definition: &conval.Definition{ + Identifier: conval.ContestIdentifier(s.contestIdentifier), + }, + } } diff --git a/go.mod b/go.mod index 5f90ba9..ec7631a 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ go 1.22.3 // replace github.com/gotk3/gotk3 => ../gotk3 require ( - github.com/ftl/cabrillo v0.2.2 + github.com/ftl/cabrillo v0.2.3 github.com/ftl/clusterix v0.1.0 github.com/ftl/conval v0.8.0 github.com/ftl/gmtry v0.0.0-20201120192810-fa4a1b99fc04 diff --git a/go.sum b/go.sum index 1c7bcc4..374a034 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ftl/cabrillo v0.2.2 h1:c54U9f14eo/aEKp1z9cfGcPfAn2feJTNbPr230hOXlQ= -github.com/ftl/cabrillo v0.2.2/go.mod h1:KYCrmgZXhXuta03bS8fnD27bJoRSmP/mvkzCV7lMU1w= +github.com/ftl/cabrillo v0.2.3 h1:x2Adf24QX6zQ0/OX12LJ6+2yp9sZBUpNV4Xsxb2w0H0= +github.com/ftl/cabrillo v0.2.3/go.mod h1:yrVvhb4datmP7OTEfX6gpEsTP8QNpXH0LAoatwvsjCI= github.com/ftl/clusterix v0.1.0 h1:+fbTybTvkVorx3B4zZ3DBiVbmLV0hhFpfDGW50Ss9cg= github.com/ftl/clusterix v0.1.0/go.mod h1:N89RHOExeAbnWqoXs/MD76uackK2/9Dcu+FooVq1tKg= github.com/ftl/conval v0.8.0 h1:ZD1b+YpNne8ED53jmDR6l3Amv+wtOveLwHQSPSGgTMc= diff --git a/ui/app.go b/ui/app.go index 36ce772..636a21f 100644 --- a/ui/app.go +++ b/ui/app.go @@ -95,8 +95,8 @@ func (a *application) activate() { a.spotsWindow = setupSpotsWindow(a.windowGeometry, a.style, a.controller.Bandmap) a.settingsDialog = setupSettingsDialog(a.mainWindow.window, a.controller.Settings) a.keyerSettingsDialog = setupKeyerSettingsDialog(a.mainWindow.window, a.controller.Keyer) - a.newContestDialog = setupNewContestDialog(a.mainWindow.window, a.controller.NewContestDialog) - a.exportCabrilloDialog = setupExportCabrilloDialog(a.mainWindow.window, a.controller.ExportCabrillo) + a.newContestDialog = setupNewContestDialog(a.mainWindow.window, a.controller.NewContestController) + a.exportCabrilloDialog = setupExportCabrilloDialog(a.mainWindow.window, a.controller.ExportCabrilloController) a.mainWindow.SetMainMenuController(a.controller) a.mainWindow.SetRadioMenuController(a.controller) @@ -125,8 +125,8 @@ func (a *application) activate() { a.controller.Bandmap.SetView(a.spotsWindow) a.controller.Settings.SetView(a.settingsDialog) a.controller.Settings.Notify(a.mainWindow) - a.controller.NewContestDialog.SetView(a.newContestDialog) - a.controller.ExportCabrilloDialog.SetView(a.exportCabrilloDialog) + a.controller.NewContestController.SetView(a.newContestDialog) + a.controller.ExportCabrilloController.SetView(a.exportCabrilloDialog) a.controller.Clusters.SetView(a.mainWindow) a.controller.Parrot.SetView(a.mainWindow) diff --git a/ui/exportCabrilloDialog.go b/ui/exportCabrilloDialog.go index 71ec162..be4b4cf 100644 --- a/ui/exportCabrilloDialog.go +++ b/ui/exportCabrilloDialog.go @@ -7,25 +7,39 @@ import ( type exportCabrilloDialog struct { dialog *gtk.Dialog parent gtk.IWidget + + controller ExportCabrilloController + view *exportCabrilloView + + openAfterExport bool } func setupExportCabrilloDialog(parent gtk.IWidget, controller ExportCabrilloController) *exportCabrilloDialog { result := &exportCabrilloDialog{ - parent: parent, + parent: parent, + controller: controller, } return result } func (d *exportCabrilloDialog) onDestroy() { d.dialog = nil + d.view = nil } func (d *exportCabrilloDialog) Show() bool { - label, _ := gtk.LabelNew("Export the log as Cabrillo format.") - + d.view = &exportCabrilloView{} grid, _ := gtk.GridNew() grid.SetOrientation(gtk.ORIENTATION_VERTICAL) - grid.Add(label) + + label, _ := gtk.LabelNew("Export the log as Cabrillo format.") + grid.Attach(label, 0, 0, 2, 1) + + d.view.openAfterExportCheckButton, _ = gtk.CheckButtonNewWithLabel("Open the file after export") + d.view.openAfterExportCheckButton.SetActive(d.openAfterExport) + grid.Attach(d.view.openAfterExportCheckButton, 0, 1, 2, 1) + + d.view.setup(d.controller) dialog, _ := gtk.DialogNew() d.dialog = dialog @@ -46,6 +60,11 @@ func (d *exportCabrilloDialog) Show() bool { d.dialog.Close() d.dialog.Destroy() d.dialog = nil + d.view = nil return result } + +func (d *exportCabrilloDialog) SetOpenAfterExport(open bool) { + d.openAfterExport = open +} diff --git a/ui/exportCabrilloView.go b/ui/exportCabrilloView.go index 4c17faf..b6eb3ca 100644 --- a/ui/exportCabrilloView.go +++ b/ui/exportCabrilloView.go @@ -1,4 +1,22 @@ package ui +import "github.com/gotk3/gotk3/gtk" + type ExportCabrilloController interface { + SetOpenAfterExport(bool) +} + +type exportCabrilloView struct { + controller ExportCabrilloController + + openAfterExportCheckButton *gtk.CheckButton +} + +func (v *exportCabrilloView) setup(controller ExportCabrilloController) { + v.controller = controller + v.openAfterExportCheckButton.Connect("toggled", v.onOpenAfterExportToggled) +} + +func (v *exportCabrilloView) onOpenAfterExportToggled() { + v.controller.SetOpenAfterExport(v.openAfterExportCheckButton.GetActive()) } From 23610ea302b911b5b4c38d28c58fe5bef991fa5a Mon Sep 17 00:00:00 2001 From: Florian Thienel Date: Tue, 24 Dec 2024 15:09:17 +0100 Subject: [PATCH 3/4] enter the required category entries in the export dialog Signed-off-by: Florian Thienel --- core/export/cabrillo/cabrillo.go | 131 +++++++++++++++++++++++++++++-- core/export/cabrillo/convert.go | 92 ++++++++++++++++++++++ ui/exportCabrilloDialog.go | 117 ++++++++++++++++++++++++++- ui/exportCabrilloView.go | 50 +++++++++++- 4 files changed, 380 insertions(+), 10 deletions(-) create mode 100644 core/export/cabrillo/convert.go diff --git a/core/export/cabrillo/cabrillo.go b/core/export/cabrillo/cabrillo.go index 36109c6..4f7401f 100644 --- a/core/export/cabrillo/cabrillo.go +++ b/core/export/cabrillo/cabrillo.go @@ -3,11 +3,13 @@ package cabrillo import ( "fmt" "io" + "log" "strings" "text/template" "time" "github.com/ftl/cabrillo" + "github.com/ftl/conval" "github.com/ftl/hamradio/callsign" "github.com/ftl/hellocontest/core" ) @@ -15,12 +17,21 @@ import ( type View interface { Show() bool + SetCategoryAssisted(bool) + SetCategoryBand(string) + SetCategoryMode(string) + SetCategoryOperator(string) + SetCategoryPower(string) SetOpenAfterExport(bool) } type Controller struct { view View + definition *conval.Definition + category cabrillo.Category + name string + email string openAfterExport bool } @@ -44,6 +55,9 @@ func (c *Controller) SetView(view View) { } func (c *Controller) Run(settings core.Settings, claimedScore int, qsos []core.QSO) (*cabrillo.Log, bool, bool) { + c.definition = settings.Contest().Definition + + c.updateCategorySettings() c.view.SetOpenAfterExport(c.openAfterExport) accepted := c.view.Show() if !accepted { @@ -51,10 +65,120 @@ func (c *Controller) Run(settings core.Settings, claimedScore int, qsos []core.Q } export := createCabrilloLog(settings, claimedScore, qsos) + export.Category = c.category return export, c.openAfterExport, true } +func (c *Controller) Categories() []string { + if c.definition == nil { + return nil + } + result := make([]string, len(c.definition.Categories)) + for i, category := range c.definition.Categories { + result[i] = category.Name + } + return result +} + +func (c *Controller) SetCategory(name string) { + category, found := c.findCategory(name) + if !found { + log.Printf("no category with name %q found", name) + return + } + + c.category.Assisted = convalToCabrilloAssisted(category) + c.category.Band = convalToCabrilloBand(category, c.definition.Bands) + c.category.Mode = convalToCabrilloMode(category, c.definition.Modes) + c.category.Operator = convalToCabrilloOperator(category) + c.category.Power = convalToCabrilloPower(category) + c.updateCategorySettings() +} + +func (c *Controller) updateCategorySettings() { + log.Printf("new category settings: %+v", c.category) + c.view.SetCategoryAssisted(c.category.Assisted == cabrillo.Assisted) + c.view.SetCategoryBand(string(c.category.Band)) + c.view.SetCategoryMode(string(c.category.Mode)) + c.view.SetCategoryOperator(string(c.category.Operator)) + c.view.SetCategoryPower(string(c.category.Power)) +} + +func (c *Controller) findCategory(name string) (conval.Category, bool) { + if c.definition == nil { + return conval.Category{}, false + } + for _, category := range c.definition.Categories { + if category.Name == name { + return category, true + } + } + return conval.Category{}, false +} + +func (c *Controller) SetCategoryAssisted(assisted bool) { + if assisted { + c.category.Assisted = cabrillo.Assisted + } else { + c.category.Assisted = cabrillo.NonAssisted + } +} + +func (c *Controller) CategoryBands() []string { + if c.definition.Bands == nil { + return []string{ + "ALL", "160M", "80M", "40M", "20M", "15M", "10M", "6M", "4M", "2M", "222", "432", + "902", "1.2G", "2.3G", "3.4G", "5.7G", "10G", "24G", "47G", "75G", "122G", "134G", + "241G", "LIGHT", "VHF-3-BAND", "VHF-FM-ONLY", + } + } + result := make([]string, len(c.definition.Bands)+1) + result[0] = "ALL" + for i, band := range c.definition.Bands { + result[i+1] = string(convertBand(band)) + } + return result +} + +func (c *Controller) SetCategoryBand(band string) { + c.category.Band = cabrillo.CategoryBand(strings.ToUpper(band)) +} + +func (c *Controller) CategoryModes() []string { + if c.definition.Modes == nil { + return []string{"CW", "PH", "RY", "DG", "FM", "MIXED"} + } + result := make([]string, len(c.definition.Modes)) + for i, mode := range c.definition.Modes { + result[i] = string(convertMode(mode)) + } + if len(result) > 1 { + result = append(result, "MIXED") + } + return result +} + +func (c *Controller) SetCategoryMode(mode string) { + c.category.Mode = cabrillo.CategoryMode(strings.ToUpper(mode)) +} + +func (c *Controller) CategoryOperators() []string { + return []string{"SINGLE-OP", "MULTI-OP", "CHECKLOG"} +} + +func (c *Controller) SetCategoryOperator(operator string) { + c.category.Operator = cabrillo.CategoryOperator(strings.ToUpper(operator)) +} + +func (c *Controller) CategoryPowers() []string { + return []string{"QRP", "LOW", "HIGH"} +} + +func (c *Controller) SetCategoryPower(power string) { + c.category.Power = cabrillo.CategoryPower(strings.ToUpper(power)) +} + func (c *Controller) SetOpenAfterExport(open bool) { c.openAfterExport = open } @@ -67,6 +191,7 @@ func createCabrilloLog(settings core.Settings, claimedScore int, qsos []core.QSO export.Operators = []callsign.Callsign{settings.Station().Operator} export.GridLocator = settings.Station().Locator export.ClaimedScore = claimedScore + export.Certificate = true qsoData := make([]cabrillo.QSO, 0, len(qsos)) ignoredQSOs := make([]cabrillo.QSO, 0, len(qsos)) @@ -87,11 +212,7 @@ func createCabrilloLog(settings core.Settings, claimedScore int, qsos []core.QSO // Export writes the given QSOs to the given writer in the Cabrillo format. // The header is very limited and needs to be completed manually after the log was written. func Export(w io.Writer, export *cabrillo.Log) error { - return cabrillo.WriteWithTags(w, export, false, false, cabrillo.CreatedByTag, cabrillo.ContestTag, - cabrillo.CallsignTag, cabrillo.OperatorsTag, cabrillo.GridLocatorTag, cabrillo.ClaimedScoreTag, - cabrillo.CategoryAssistedTag, cabrillo.CategoryBandTag, cabrillo.CategoryModeTag, - cabrillo.CategoryOperatorTag, cabrillo.CategoryPowerTag, cabrillo.ClubTag, cabrillo.NameTag, - cabrillo.EmailTag) + return cabrillo.Write(w, export, false) } var qrg = map[core.Band]string{ diff --git a/core/export/cabrillo/convert.go b/core/export/cabrillo/convert.go new file mode 100644 index 0000000..349004f --- /dev/null +++ b/core/export/cabrillo/convert.go @@ -0,0 +1,92 @@ +package cabrillo + +import ( + "strings" + + "github.com/ftl/cabrillo" + "github.com/ftl/conval" +) + +func convalToCabrilloAssisted(category conval.Category) cabrillo.CategoryAssisted { + if category.Assisted { + return cabrillo.Assisted + } else { + return cabrillo.NonAssisted + } +} + +func convalToCabrilloBand(category conval.Category, availableBands []conval.ContestBand) cabrillo.CategoryBand { + if category.BandCount == conval.AllBands { + return cabrillo.BandAll + } + if (len(category.Bands) > 0) && (category.Bands[0] == conval.BandAll) { + return cabrillo.BandAll + } + if len(availableBands) == 1 { + return convertBand(availableBands[0]) + } + return "" +} + +func convertBand(band conval.ContestBand) cabrillo.CategoryBand { + return cabrillo.CategoryBand(strings.ToUpper(string(band))) +} + +func convalToCabrilloMode(category conval.Category, availableModes []conval.Mode) cabrillo.CategoryMode { + if len(category.Modes) > 1 { + return cabrillo.ModeMIXED + } + var mode conval.Mode + if len(category.Modes) == 1 { + mode = category.Modes[0] + } else if len(availableModes) == 1 { + mode = availableModes[0] + } + return convertMode(mode) +} + +func convertMode(mode conval.Mode) cabrillo.CategoryMode { + switch mode { + case conval.ModeCW: + return cabrillo.ModeCW + case conval.ModeSSB: + return cabrillo.ModeSSB + case conval.ModeRTTY: + return cabrillo.ModeRTTY + case conval.ModeFM: + return cabrillo.ModeFM + case conval.ModeDigital: + return cabrillo.ModeDIGI + case conval.ModeALL: + return cabrillo.ModeMIXED + default: + return "" + } +} + +func convalToCabrilloOperator(category conval.Category) cabrillo.CategoryOperator { + if strings.ToUpper(category.Name) == "CHECKLOG" { + return cabrillo.Checklog + } + switch category.Operator { + case conval.SingleOperator: + return cabrillo.SingleOperator + case conval.MultiOperator: + return cabrillo.MultiOperator + default: + return "" + } +} + +func convalToCabrilloPower(category conval.Category) cabrillo.CategoryPower { + switch category.Power { + case conval.HighPower: + return cabrillo.HighPower + case conval.LowPower: + return cabrillo.LowPower + case conval.QRPPower: + return cabrillo.QRP + default: + return "" + } +} diff --git a/ui/exportCabrilloDialog.go b/ui/exportCabrilloDialog.go index be4b4cf..5cdff9c 100644 --- a/ui/exportCabrilloDialog.go +++ b/ui/exportCabrilloDialog.go @@ -11,7 +11,12 @@ type exportCabrilloDialog struct { controller ExportCabrilloController view *exportCabrilloView - openAfterExport bool + categoryAssisted bool + categoryBand string + categoryMode string + categoryOperator string + categoryPower string + openAfterExport bool } func setupExportCabrilloDialog(parent gtk.IWidget, controller ExportCabrilloController) *exportCabrilloDialog { @@ -31,13 +36,82 @@ func (d *exportCabrilloDialog) Show() bool { d.view = &exportCabrilloView{} grid, _ := gtk.GridNew() grid.SetOrientation(gtk.ORIENTATION_VERTICAL) + grid.SetHExpand(true) + grid.SetVExpand(true) + grid.SetColumnSpacing(5) - label, _ := gtk.LabelNew("Export the log as Cabrillo format.") + label, _ := gtk.LabelNew("Export the log as Cabrillo file.") + label.SetHAlign(gtk.ALIGN_START) + label.SetMarginBottom(10) grid.Attach(label, 0, 0, 2, 1) + label, _ = gtk.LabelNew("Category") + label.SetHAlign(gtk.ALIGN_END) + grid.Attach(label, 0, 1, 1, 1) + d.view.categoriesCombo, _ = gtk.ComboBoxTextNew() + d.view.categoriesCombo.Append("", "") + for _, category := range d.controller.Categories() { + d.view.categoriesCombo.Append(category, category) + } + d.view.categoriesCombo.SetActive(0) + grid.Attach(d.view.categoriesCombo, 1, 1, 1, 1) + + d.view.categoryAssistedCheckButton, _ = gtk.CheckButtonNewWithLabel("Assisted") + d.view.categoryAssistedCheckButton.SetActive(d.categoryAssisted) + grid.Attach(d.view.categoryAssistedCheckButton, 1, 2, 1, 1) + + label, _ = gtk.LabelNew("Band") + label.SetHAlign(gtk.ALIGN_END) + grid.Attach(label, 0, 3, 1, 1) + d.view.categoryBandCombo, _ = gtk.ComboBoxTextNew() + d.view.categoryBandCombo.Append("", "") + for _, band := range d.controller.CategoryBands() { + d.view.categoryBandCombo.Append(band, band) + } + d.view.categoryBandCombo.SetActiveID(d.categoryBand) + grid.Attach(d.view.categoryBandCombo, 1, 3, 1, 1) + + label, _ = gtk.LabelNew("Mode") + label.SetHAlign(gtk.ALIGN_END) + grid.Attach(label, 0, 4, 1, 1) + d.view.categoryModeCombo, _ = gtk.ComboBoxTextNew() + d.view.categoryModeCombo.Append("", "") + for _, mode := range d.controller.CategoryModes() { + d.view.categoryModeCombo.Append(mode, mode) + } + d.view.categoryModeCombo.SetActiveID(d.categoryMode) + grid.Attach(d.view.categoryModeCombo, 1, 4, 1, 1) + + label, _ = gtk.LabelNew("Operator") + label.SetHAlign(gtk.ALIGN_END) + grid.Attach(label, 0, 5, 1, 1) + d.view.categoryOperatorCombo, _ = gtk.ComboBoxTextNew() + d.view.categoryOperatorCombo.Append("", "") + for _, operator := range d.controller.CategoryOperators() { + d.view.categoryOperatorCombo.Append(operator, operator) + } + d.view.categoryOperatorCombo.SetActiveID(d.categoryOperator) + grid.Attach(d.view.categoryOperatorCombo, 1, 5, 1, 1) + + label, _ = gtk.LabelNew("Power") + label.SetHAlign(gtk.ALIGN_END) + grid.Attach(label, 0, 6, 1, 1) + d.view.categoryPowerCombo, _ = gtk.ComboBoxTextNew() + d.view.categoryPowerCombo.Append("", "") + for _, power := range d.controller.CategoryPowers() { + d.view.categoryPowerCombo.Append(power, power) + } + d.view.categoryPowerCombo.SetActiveID(d.categoryPower) + grid.Attach(d.view.categoryPowerCombo, 1, 6, 1, 1) + + separator, _ := gtk.SeparatorNew(gtk.ORIENTATION_HORIZONTAL) + separator.SetHExpand(true) + separator.SetVExpand(true) + grid.Attach(separator, 0, 7, 2, 1) + d.view.openAfterExportCheckButton, _ = gtk.CheckButtonNewWithLabel("Open the file after export") d.view.openAfterExportCheckButton.SetActive(d.openAfterExport) - grid.Attach(d.view.openAfterExportCheckButton, 0, 1, 2, 1) + grid.Attach(d.view.openAfterExportCheckButton, 0, 8, 2, 1) d.view.setup(d.controller) @@ -47,7 +121,7 @@ func (d *exportCabrilloDialog) Show() bool { d.dialog.SetTransientFor(nil) d.dialog.SetPosition(gtk.WIN_POS_CENTER) d.dialog.Connect("destroy", d.onDestroy) - d.dialog.SetTitle("Export Log as Cabrillo") + d.dialog.SetTitle("Export Cabrillo") d.dialog.SetDefaultResponse(gtk.RESPONSE_OK) d.dialog.SetModal(true) contentArea, _ := d.dialog.GetContentArea() @@ -65,6 +139,41 @@ func (d *exportCabrilloDialog) Show() bool { return result } +func (d *exportCabrilloDialog) SetCategoryAssisted(assisted bool) { + d.categoryAssisted = assisted + if d.view != nil { + d.view.categoryAssistedCheckButton.SetActive(assisted) + } +} + +func (d *exportCabrilloDialog) SetCategoryBand(band string) { + d.categoryBand = band + if d.view != nil { + d.view.categoryBandCombo.SetActiveID(band) + } +} + +func (d *exportCabrilloDialog) SetCategoryMode(mode string) { + d.categoryMode = mode + if d.view != nil { + d.view.categoryModeCombo.SetActiveID(mode) + } +} + +func (d *exportCabrilloDialog) SetCategoryOperator(operator string) { + d.categoryOperator = operator + if d.view != nil { + d.view.categoryOperatorCombo.SetActiveID(operator) + } +} + +func (d *exportCabrilloDialog) SetCategoryPower(power string) { + d.categoryPower = power + if d.view != nil { + d.view.categoryPowerCombo.SetActiveID(power) + } +} + func (d *exportCabrilloDialog) SetOpenAfterExport(open bool) { d.openAfterExport = open } diff --git a/ui/exportCabrilloView.go b/ui/exportCabrilloView.go index b6eb3ca..7839504 100644 --- a/ui/exportCabrilloView.go +++ b/ui/exportCabrilloView.go @@ -3,20 +3,68 @@ package ui import "github.com/gotk3/gotk3/gtk" type ExportCabrilloController interface { + Categories() []string + CategoryBands() []string + CategoryModes() []string + CategoryOperators() []string + CategoryPowers() []string + + SetCategory(string) + SetCategoryAssisted(bool) + SetCategoryBand(string) + SetCategoryMode(string) + SetCategoryOperator(string) + SetCategoryPower(string) SetOpenAfterExport(bool) } type exportCabrilloView struct { controller ExportCabrilloController - openAfterExportCheckButton *gtk.CheckButton + categoriesCombo *gtk.ComboBoxText + categoryAssistedCheckButton *gtk.CheckButton + categoryBandCombo *gtk.ComboBoxText + categoryModeCombo *gtk.ComboBoxText + categoryOperatorCombo *gtk.ComboBoxText + categoryPowerCombo *gtk.ComboBoxText + openAfterExportCheckButton *gtk.CheckButton } func (v *exportCabrilloView) setup(controller ExportCabrilloController) { v.controller = controller + v.categoriesCombo.Connect("changed", v.onCategoryChanged) + v.categoryAssistedCheckButton.Connect("toggled", v.onCategoryAssistedToggled) + v.categoryBandCombo.Connect("changed", v.onCategoryBandChanged) + v.categoryModeCombo.Connect("changed", v.onCategoryModeChanged) + v.categoryOperatorCombo.Connect("changed", v.onCategoryOperatorChanged) + v.categoryPowerCombo.Connect("changed", v.onCategoryPowerChanged) v.openAfterExportCheckButton.Connect("toggled", v.onOpenAfterExportToggled) } +func (v *exportCabrilloView) onCategoryChanged() { + v.controller.SetCategory(v.categoriesCombo.GetActiveText()) +} + +func (v *exportCabrilloView) onCategoryAssistedToggled() { + v.controller.SetCategoryAssisted(v.categoryAssistedCheckButton.GetActive()) +} + +func (v *exportCabrilloView) onCategoryBandChanged() { + v.controller.SetCategoryBand(v.categoryBandCombo.GetActiveText()) +} + +func (v *exportCabrilloView) onCategoryModeChanged() { + v.controller.SetCategoryMode(v.categoryModeCombo.GetActiveText()) +} + +func (v *exportCabrilloView) onCategoryOperatorChanged() { + v.controller.SetCategoryOperator(v.categoryOperatorCombo.GetActiveText()) +} + +func (v *exportCabrilloView) onCategoryPowerChanged() { + v.controller.SetCategoryPower(v.categoryPowerCombo.GetActiveText()) +} + func (v *exportCabrilloView) onOpenAfterExportToggled() { v.controller.SetOpenAfterExport(v.openAfterExportCheckButton.GetActive()) } From 23f8bc0e8539f05de418722c1dd91dacf2f2c199 Mon Sep 17 00:00:00 2001 From: Florian Thienel Date: Tue, 24 Dec 2024 15:27:03 +0100 Subject: [PATCH 4/4] enter name and email in the export dialog Signed-off-by: Florian Thienel --- core/export/cabrillo/cabrillo.go | 14 +++++++++ core/export/cabrillo/cabrillo_test.go | 9 +----- ui/exportCabrilloDialog.go | 42 +++++++++++++++++++++++++-- ui/exportCabrilloView.go | 16 ++++++++++ 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/core/export/cabrillo/cabrillo.go b/core/export/cabrillo/cabrillo.go index 4f7401f..308b6e7 100644 --- a/core/export/cabrillo/cabrillo.go +++ b/core/export/cabrillo/cabrillo.go @@ -22,6 +22,8 @@ type View interface { SetCategoryMode(string) SetCategoryOperator(string) SetCategoryPower(string) + SetName(string) + SetEmail(string) SetOpenAfterExport(bool) } @@ -58,6 +60,8 @@ func (c *Controller) Run(settings core.Settings, claimedScore int, qsos []core.Q c.definition = settings.Contest().Definition c.updateCategorySettings() + c.view.SetName(c.name) + c.view.SetEmail(c.email) c.view.SetOpenAfterExport(c.openAfterExport) accepted := c.view.Show() if !accepted { @@ -66,6 +70,8 @@ func (c *Controller) Run(settings core.Settings, claimedScore int, qsos []core.Q export := createCabrilloLog(settings, claimedScore, qsos) export.Category = c.category + export.Name = c.name + export.Email = c.email return export, c.openAfterExport, true } @@ -179,6 +185,14 @@ func (c *Controller) SetCategoryPower(power string) { c.category.Power = cabrillo.CategoryPower(strings.ToUpper(power)) } +func (c *Controller) SetName(name string) { + c.name = name +} + +func (c *Controller) SetEmail(email string) { + c.email = email +} + func (c *Controller) SetOpenAfterExport(open bool) { c.openAfterExport = open } diff --git a/core/export/cabrillo/cabrillo_test.go b/core/export/cabrillo/cabrillo_test.go index 3333957..39d89e7 100644 --- a/core/export/cabrillo/cabrillo_test.go +++ b/core/export/cabrillo/cabrillo_test.go @@ -95,14 +95,7 @@ CALLSIGN: AA1ZZZ OPERATORS: AA2ZZZ GRID-LOCATOR: AA00aa CLAIMED-SCORE: 123 -CATEGORY-ASSISTED: -CATEGORY-BAND: -CATEGORY-MODE: -CATEGORY-OPERATOR: -CATEGORY-POWER: -CLUB: -NAME: -EMAIL: +CERTIFICATE: YES QSO: 7000 CW 2009-05-30 0002 AA1ZZZ 599 001 ABC S50A 589 004 DEF END-OF-LOG: ` diff --git a/ui/exportCabrilloDialog.go b/ui/exportCabrilloDialog.go index 5cdff9c..6e7512b 100644 --- a/ui/exportCabrilloDialog.go +++ b/ui/exportCabrilloDialog.go @@ -16,6 +16,8 @@ type exportCabrilloDialog struct { categoryMode string categoryOperator string categoryPower string + name string + email string openAfterExport bool } @@ -106,18 +108,38 @@ func (d *exportCabrilloDialog) Show() bool { separator, _ := gtk.SeparatorNew(gtk.ORIENTATION_HORIZONTAL) separator.SetHExpand(true) - separator.SetVExpand(true) + separator.SetMarginTop(5) + separator.SetMarginBottom(5) grid.Attach(separator, 0, 7, 2, 1) + label, _ = gtk.LabelNew("Name") + label.SetHAlign(gtk.ALIGN_END) + grid.Attach(label, 0, 8, 1, 1) + d.view.nameEntry, _ = gtk.EntryNew() + d.view.nameEntry.SetText(d.name) + grid.Attach(d.view.nameEntry, 1, 8, 1, 1) + + label, _ = gtk.LabelNew("Email") + label.SetHAlign(gtk.ALIGN_END) + grid.Attach(label, 0, 9, 1, 1) + d.view.emailEntry, _ = gtk.EntryNew() + d.view.emailEntry.SetText(d.email) + grid.Attach(d.view.emailEntry, 1, 9, 1, 1) + + separator, _ = gtk.SeparatorNew(gtk.ORIENTATION_HORIZONTAL) + separator.SetHExpand(true) + separator.SetVExpand(true) + grid.Attach(separator, 0, 10, 2, 1) + d.view.openAfterExportCheckButton, _ = gtk.CheckButtonNewWithLabel("Open the file after export") d.view.openAfterExportCheckButton.SetActive(d.openAfterExport) - grid.Attach(d.view.openAfterExportCheckButton, 0, 8, 2, 1) + grid.Attach(d.view.openAfterExportCheckButton, 0, 11, 2, 1) d.view.setup(d.controller) dialog, _ := gtk.DialogNew() d.dialog = dialog - d.dialog.SetDefaultSize(400, 300) + d.dialog.SetDefaultSize(400, 400) d.dialog.SetTransientFor(nil) d.dialog.SetPosition(gtk.WIN_POS_CENTER) d.dialog.Connect("destroy", d.onDestroy) @@ -174,6 +196,20 @@ func (d *exportCabrilloDialog) SetCategoryPower(power string) { } } +func (d *exportCabrilloDialog) SetName(name string) { + d.name = name + if d.view != nil { + d.view.nameEntry.SetText(name) + } +} + +func (d *exportCabrilloDialog) SetEmail(email string) { + d.email = email + if d.view != nil { + d.view.emailEntry.SetText(email) + } +} + func (d *exportCabrilloDialog) SetOpenAfterExport(open bool) { d.openAfterExport = open } diff --git a/ui/exportCabrilloView.go b/ui/exportCabrilloView.go index 7839504..b8d0313 100644 --- a/ui/exportCabrilloView.go +++ b/ui/exportCabrilloView.go @@ -15,6 +15,8 @@ type ExportCabrilloController interface { SetCategoryMode(string) SetCategoryOperator(string) SetCategoryPower(string) + SetName(string) + SetEmail(string) SetOpenAfterExport(bool) } @@ -27,6 +29,8 @@ type exportCabrilloView struct { categoryModeCombo *gtk.ComboBoxText categoryOperatorCombo *gtk.ComboBoxText categoryPowerCombo *gtk.ComboBoxText + nameEntry *gtk.Entry + emailEntry *gtk.Entry openAfterExportCheckButton *gtk.CheckButton } @@ -38,6 +42,8 @@ func (v *exportCabrilloView) setup(controller ExportCabrilloController) { v.categoryModeCombo.Connect("changed", v.onCategoryModeChanged) v.categoryOperatorCombo.Connect("changed", v.onCategoryOperatorChanged) v.categoryPowerCombo.Connect("changed", v.onCategoryPowerChanged) + v.nameEntry.Connect("changed", v.onNameChanged) + v.emailEntry.Connect("changed", v.onEmailChanged) v.openAfterExportCheckButton.Connect("toggled", v.onOpenAfterExportToggled) } @@ -65,6 +71,16 @@ func (v *exportCabrilloView) onCategoryPowerChanged() { v.controller.SetCategoryPower(v.categoryPowerCombo.GetActiveText()) } +func (v *exportCabrilloView) onNameChanged() { + text, _ := v.nameEntry.GetText() + v.controller.SetName(text) +} + +func (v *exportCabrilloView) onEmailChanged() { + text, _ := v.emailEntry.GetText() + v.controller.SetEmail(text) +} + func (v *exportCabrilloView) onOpenAfterExportToggled() { v.controller.SetOpenAfterExport(v.openAfterExportCheckButton.GetActive()) }