merge

Simple tool to quickly merge datasets for statistical analysis
git clone git://git.wrycode.com/wrycode/archive/merge.git
Log | Files | Refs | README | LICENSE

commit eda1ae1284c2f846212efd9a8a6001d8e1a3aff7
parent 8b412c0c35263c9a92799e097637373926fe99fa
Author: Nick Econopouly <wry@mm.st>
Date:   Sun,  5 Apr 2020 02:33:12 -0400

Refactor and comment main.go

Diffstat:
Mmain.go | 212+++++++++++++++++++++++--------------------------------------------------------
1 file changed, 60 insertions(+), 152 deletions(-)

diff --git a/main.go b/main.go @@ -6,7 +6,6 @@ import ( "log" "path/filepath" "strings" - "bytes" "C" "unsafe" "github.com/360EntSecGroup-Skylar/excelize" @@ -16,6 +15,18 @@ import ( // "github.com/gotk3/gotk3/gdk" ) +// object that holds every widget +type view struct { + mainBox *gtk.Box + datasetListBox *gtk.ListBox + addButton *gtk.Button + addDatasetDialog *gtk.FileChooserNativeDialog + saveDialog *gtk.FileChooserNativeDialog + errorLabel *gtk.Label + mergeButton *gtk.Button +} + +// gtk boilerplate func windowSetup() *gtk.Window { os.Setenv("GSETTINGS_SCHEMA_DIR", ".\\share\\glib-2.0\\schemas") @@ -36,6 +47,46 @@ func windowSetup() *gtk.Window { return window } +// returns an initial view object (a skeleton that still needs the +// widgets initialized) +func viewSetup() view { + + var v view + var err error + + // main box container + v.mainBox, err = gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5) + if err != nil { + log.Fatal("Unable to create grid: ", err) + } + + // listBox of dataset names + remove buttons + v.datasetListBox, err = gtk.ListBoxNew() + v.mainBox.PackStart(v.datasetListBox,false, false, 0) + + // button to add new datasets + v.addButton, err = gtk.ButtonNewWithLabel("Add Dataset(s)") + if err != nil { + log.Fatal("unable to create addButton") + } + v.mainBox.PackStart(v.addButton, false, false, 0) + + + // merge datasets + v.mergeButton, err = gtk.ButtonNewWithLabel("Merge Datasets") + if err != nil { + log.Fatal("Unable to create mergeButton", err) + } + v.mainBox.PackStart(v.mergeButton, false, false, 0) + + v.errorLabel = newLabel("") + v.mainBox.PackStart(v.errorLabel, false, false, 0) + + return v +} + +// connect the "Add Dataset" button to the dialog box and the update +// the list of datasets func addButtonSetup(v view, filepaths *[]string, window *gtk.Window) { var err error @@ -163,6 +214,8 @@ func mergeButtonSetup(v view, filenames *[]string, window *gtk.Window) { }) } +// rebuild the list of selected dataset files (with "delete" buttons) +// and refresh the window func rebuildDatasetListBox(list *gtk.ListBox, filenames *[]string, window *gtk.Window) { // clear list list.GetChildren().Foreach(func(item interface{}) { @@ -201,23 +254,7 @@ func rebuildDatasetListBox(list *gtk.ListBox, filenames *[]string, window *gtk.W list.Insert(box, 0) } } -func newHeadline(s string) *gtk.Label { - if len(s) < 115 { - var b bytes.Buffer - for i := len(s); i < 115; i++ { - b.WriteString(" ") - } - s += b.String() - } - l := newLabel(s) - style, err := l.GetStyleContext() - if err != nil { - log.Fatal("error getting style context") - } - style.AddClass("section-title") - return l -} func newLabel(s string) *gtk.Label { l, err := gtk.LabelNew(s) if err != nil { @@ -237,7 +274,6 @@ func goodFileExtensions(filepaths *[]string) bool { return true } - func pullExcel(path string) [][]string { var rows [][]string f, err := excelize.OpenFile(path) @@ -298,7 +334,6 @@ func pullODS(path string) [][]string { rows = d.Table[0].Strings() return rows - } // see import.go for Dataset fields and methods used in this file @@ -348,147 +383,20 @@ func main() { window := windowSetup() - // main box container - mainBox, err := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5) - if err != nil { - log.Fatal("Unable to create grid: ", err) - } + // struct containing the main widgets + v := viewSetup() // holds the paths to the datasets to be merged; this var is // passed around when removing and adding datasets filepaths := &[]string{} - // listBox of dataset names + remove buttons - datasetListBox, err := gtk.ListBoxNew() - mainBox.PackStart(datasetListBox,false, false, 0) + addButtonSetup(v, filepaths, window) + mergeButtonSetup(v, filepaths, window) // refresh the (empty) list of datasets for the first time - rebuildDatasetListBox(datasetListBox, filepaths, window) - - // add new datasets using native file chooser - addButton, err := gtk.ButtonNewWithLabel("Add Dataset(s)") - if err != nil { - log.Fatal("unable to create addButton") - } - mainBox.PackStart(addButton, false, false, 0) - - // native file chooser - addDatasetDialog, err := gtk.FileChooserNativeDialogNew("open",window,gtk.FILE_CHOOSER_ACTION_OPEN,"open","cancel") - // user can add multiple datasets - addDatasetDialog.SetSelectMultiple(true) - - _, err = addButton.Connect("clicked", func() { - _ = addDatasetDialog.Run() - list, err := addDatasetDialog.GetFilenames() - if err != nil { - log.Fatal("Error getting filenames") - } - - // list is a *glib.SList returned by GetFilenames. - // glib.SList.Foreach iterates over items in a list - // and provides unsafe.Pointers to the C data. Here we - // can convert the C []chars to Golang strings using - // cgo - list.Foreach(func(ptr unsafe.Pointer) { - filename := C.GoString((*C.char)(ptr)) - // add path to list - *filepaths = append(*filepaths, filename) - }) - // refresh the view - rebuildDatasetListBox(datasetListBox, filepaths, window) - window.ShowAll() - }) - - // merge datasets - mergeButton, err := gtk.ButtonNewWithLabel("Merge Datasets") - if err != nil { - log.Fatal("Unable to create mergeButton", err) - } - mainBox.PackStart(mergeButton, false, false, 0) - - errorLabel := newLabel("") - mainBox.PackStart(errorLabel, false, false, 0) - - // another native file chooser - saveDialog, err := gtk.FileChooserNativeDialogNew("save",window,gtk.FILE_CHOOSER_ACTION_SAVE,"save","cancel") - - // filter for acceptable filetypes to save to - CsvFilter, err := gtk.FileFilterNew() - CsvFilter.AddPattern("*.csv") - CsvFilter.SetName("Comma Separated Values") - - AllFilter, err := gtk.FileFilterNew() - AllFilter.AddPattern("*") - AllFilter.SetName("All File Types") - - ExcelFilter, err := gtk.FileFilterNew() - ExcelFilter.AddPattern("*.xlsx") - ExcelFilter.SetName("Microsoft Excel") - // saveFilter.AddMimeType("ods") - // saveFilter.AddMimeType("xlsx") - - saveDialog.AddFilter(CsvFilter) - saveDialog.AddFilter(ExcelFilter) - saveDialog.AddFilter(AllFilter) - saveDialog.SetFilter(AllFilter) - saveDialog.SetFilename("merged.xlsx") - - saveDialog.SetDoOverwriteConfirmation(true) - - _, err = mergeButton.Connect("clicked", func() { - - // clear old error - errorLabel.SetText("") - - if goodFileExtensions(filepaths) { - _ = saveDialog.Run() - - outputFile := saveDialog.GetFilename() - if outputFile != "" { - - // supported file extensions and their associated function for pulling the raw data - fileFormat := map[string]func(string) [][]string{ - ".xlsx": pullExcel, - ".csv": pullCSV, - ".ods": pullODS, - } - - // map of basenames to the [][]string data - raws := make(map[string][][]string) - - // all datasets - datasets := make(map[string]*Dataset) - - // import dataset based on file extension - for _, path := range *filepaths { - basename := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) - ext := strings.ToLower(filepath.Ext(path)) - if _, ok := fileFormat[ext]; ok { - raws[basename] = fileFormat[ext](path) - } - for name, data := range raws { - datasets[name] = ImportDataset(name, data) - } - } - - // merge them into a single Dataset - var dataset Dataset - dataset.height = 1 // row of terms, even though it's empty - dataset.data = make(map[string][]string) - for _, d := range datasets { - mergeDatasets(&dataset,d) - } - - // export dataset - exportDataset(&dataset, outputFile) - } - - } else { - errorLabel.SetText("There was a problem with the files you chose. Make sure to choose supported spreadsheet formats.") - } - }) + rebuildDatasetListBox(v.datasetListBox, filepaths, window) - window.Add(mainBox) + window.Add(v.mainBox) window.ShowAll() gtk.Main()