From 063a8ca8372ef253e6be519d4eb94b34bfe8f2ff Mon Sep 17 00:00:00 2001 From: mappu Date: Sun, 30 Jun 2024 14:14:41 +1200 Subject: [PATCH] debconf: add as database option --- assets/vendor_debian.png | Bin 0 -> 831 bytes db_debconf.go | 142 +++++++++++++++++++++++++++++++++++++++ images.go | 2 + main.go | 22 ++++++ 4 files changed, 166 insertions(+) create mode 100644 assets/vendor_debian.png create mode 100644 db_debconf.go diff --git a/assets/vendor_debian.png b/assets/vendor_debian.png new file mode 100644 index 0000000000000000000000000000000000000000..b20786623cb65948222c987703da959466aa858a GIT binary patch literal 831 zcmV-F1Hk-=P)Nxhg23=knh3@O#hiaPGNa4Q7>`-Zc-od{GMr{O;B0n%n+P z52IL^#Sv3rBdR-XZGq`*ESr9q^^LaS9nHIwW6?0LvX98n!G1GsAOUZ z;S*u6CIbrJntHs>ZziYf{AIEh2`_@x?CDOoaJ+?;jFuCg5ccGvJ~-2&dbi)`zC9?B?{tEzO;6RkJN?l8Y8anmVBd#o#V~$P4WoJnwime0H~j_K)7-b{m8Rx72G}86AQ>P%9no2F~BLUi+PL&B^bdmW_8*QL5*4m zd6onzY{2t_!X`l{R;9BRsUGdP)+Nbo^2pdYn?Od%mb=|G-6!oQ9(9c2mAxImK5@1YVdy97D1 zNi?9Jgyp3qDE^tGX~vKiO8y1cuKC{tCP_lKP?m9{Nj`%Td;>_kd04W$+XDaq002ov JPDHLkV1hdPjZy#r literal 0 HcmV?d00001 diff --git a/db_debconf.go b/db_debconf.go new file mode 100644 index 0000000..50a8d77 --- /dev/null +++ b/db_debconf.go @@ -0,0 +1,142 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "unsafe" + + "yvbolt/debconf" + + "github.com/ying32/govcl/vcl" +) + +type debconfLoadedDatabase struct { + displayName string + db *debconf.Database + nav *vcl.TTreeNode + + arena []*navData // keepalive +} + +func (ld *debconfLoadedDatabase) DisplayName() string { + return ld.displayName +} + +func (ld *debconfLoadedDatabase) DriverName() string { + return "debconf" +} + +func (ld *debconfLoadedDatabase) RootElement() *vcl.TTreeNode { + return ld.nav +} + +func (ld *debconfLoadedDatabase) Keepalive(ndata *navData) { + ld.arena = append(ld.arena, ndata) +} + +func (ld *debconfLoadedDatabase) RenderForNav(f *TMainForm, ndata *navData) { + + // Load properties + + content := fmt.Sprintf("Entries: %d\nUnique attributes: %d\n", len(ld.db.Entries), len(ld.db.AllColumnNames)) + f.propertiesBox.SetText(content) + + // Load data + + f.contentBox.SetEnabled(false) + f.contentBox.Clear() + + // debconf always uses Key + Value as the columns + + indexes := make(map[string]int) + + f.contentBox.Columns().Clear() + for i, cname := range ld.db.AllColumnNames { + indexes[cname] = i + + col := f.contentBox.Columns().Add() + col.SetCaption(cname) + col.SetWidth(MY_WIDTH) + } + + for _, entry := range ld.db.Entries { + + cell := f.contentBox.Items().Add() + cell.SetCaption(entry.Name) + + texts := make([]string, len(ld.db.AllColumnNames)) + for _, proppair := range entry.Properties { + texts[indexes[proppair[0]]-1 /* compensate for 'Name' always being first */] = proppair[1] + } + cell.SubItems().AddStrings2(texts) + } + + // Valid + f.contentBox.SetEnabled(true) +} + +func (ld *debconfLoadedDatabase) NavChildren(ndata *navData) ([]string, error) { + // In the debconf implementation, there is only one child: "Data" + if len(ndata.bucketPath) == 0 { + return []string{"Data"}, nil + + } else { + // No children deeper than that + return []string{}, nil + } +} + +func (ld *debconfLoadedDatabase) NavContext(ndata *navData) ([]contextAction, error) { + return nil, nil // No special actions are supported +} + +func (ld *debconfLoadedDatabase) ExecQuery(query string, resultArea *vcl.TListView) { + vcl.ShowMessage("debconf doesn't support querying") +} + +func (ld *debconfLoadedDatabase) Close() { + ld.arena = nil +} + +var _ loadedDatabase = &debconfLoadedDatabase{} // interface assertion + +// + +func (f *TMainForm) debconfAddDatabaseFrom(path string) { + // TODO load in background thread to stop blocking the UI + + fh, err := os.OpenFile(path, os.O_RDONLY, 0400) + if err != nil { + vcl.ShowMessage(fmt.Sprintf("Failed to load database: %s", err.Error())) + return + } + defer fh.Close() + + db, err := debconf.Parse(fh) + if err != nil { + vcl.ShowMessage(fmt.Sprintf("Failed to load database: %s", err.Error())) + return + } + + ld := &debconfLoadedDatabase{ + db: db, + displayName: filepath.Base(path), + } + + ld.nav = f.Buckets.Items().Add(nil, ld.displayName) + ld.nav.SetHasChildren(true) // dynamically populate in OnNavExpanding + ld.nav.SetImageIndex(imgDatabase) + ld.nav.SetSelectedIndex(imgDatabase) + navData := &navData{ + ld: ld, + childrenLoaded: false, // will be loaded dynamically + bucketPath: []string{}, // empty = root + } + ld.nav.SetData(unsafe.Pointer(navData)) + + f.dbs = append(f.dbs, ld) + f.Buckets.SetSelected(ld.nav) // Select new element + + ld.Keepalive(navData) +} diff --git a/images.go b/images.go index 7c8d288..313371b 100644 --- a/images.go +++ b/images.go @@ -23,6 +23,7 @@ const ( imgTableDelete imgTableSave imgVendorCockroach + imgVendorDebian imgVendorDgraph imgVendorGithub imgVendorMySQL @@ -60,6 +61,7 @@ func loadImages(owner vcl.IComponent) *vcl.TImageList { ilist.Add(mustLoad("assets/table_delete.png"), nil) ilist.Add(mustLoad("assets/table_save.png"), nil) ilist.Add(mustLoad("assets/vendor_cockroach.png"), nil) + ilist.Add(mustLoad("assets/vendor_debian.png"), nil) ilist.Add(mustLoad("assets/vendor_dgraph.png"), nil) ilist.Add(mustLoad("assets/vendor_github.png"), nil) ilist.Add(mustLoad("assets/vendor_mysql.png"), nil) diff --git a/main.go b/main.go index c20b4bd..5d43309 100644 --- a/main.go +++ b/main.go @@ -79,6 +79,15 @@ func (f *TMainForm) OnFormCreate(sender vcl.IObject) { // + mnuFileDebconf := vcl.NewMenuItem(mnuFile) + mnuFileDebconf.SetCaption("Debconf") + mnuFileDebconf.SetImageIndex(imgVendorDebian) + mnuFile.Add(mnuFileDebconf) + + vcl_menuitem(mnuFileDebconf, "Open database...", imgDatabaseAdd, f.OnMnuFileDebianOpenClick) + + // + mnuFilePebble := vcl.NewMenuItem(mnuFile) mnuFilePebble.SetCaption("Pebble") mnuFilePebble.SetImageIndex(imgVendorCockroach) @@ -328,6 +337,19 @@ func (f *TMainForm) OnMnuFilePebbleOpenClick(sender vcl.IObject) { } } +func (f *TMainForm) OnMnuFileDebianOpenClick(sender vcl.IObject) { + dlg := vcl.NewOpenDialog(f) + dlg.SetTitle("Select a database file...") + dlg.SetFilter("Debconf database|*.dat|All files|*.*") + if runtime.GOOS == "linux" { + dlg.SetInitialDir(`/var/cache/debconf/`) + } + ret := dlg.Execute() // Fake blocking + if ret { + f.debconfAddDatabaseFrom(dlg.FileName()) + } +} + func (f *TMainForm) OnMnuFilePebbleMemoryClick(sender vcl.IObject) { f.pebbleAddDatabaseFromMemory() }