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) }