package main import ( "errors" "fmt" "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/widget" "strings" ) type DBInterface struct { application fyne.App window fyne.Window db SQLConnection } func genMainView(view fyne.CanvasObject, buttons []fyne.CanvasObject) fyne.CanvasObject { return container.NewBorder( nil, container.NewGridWithColumns(len(buttons), buttons...), nil, nil, view) } func parseQuery(box *fyne.Container) (string, error) { var query []string for _, obj := range box.Objects { constraint := obj.(*fyne.Container).Objects column := constraint[0].(*widget.Select) operator := constraint[1].(*widget.Select) value := constraint[2].(*widget.Entry) if column.SelectedIndex() == -1 { return "", errors.New("В одном из ограничений не выбрана колонка") } if operator.SelectedIndex() == -1 { return "", errors.New("В одном из ограничений не выбран оператор") } query = append(query, fmt.Sprintf("%s %s '%s'", column.Selected, operator.Selected, value.Text)) } return strings.Join(query, " AND "), nil } func (app *DBInterface) insertAdminView(table string) { app.window.SetTitle(fmt.Sprintf("Вставка в таблицу [%s] (Режим администратора)", table)) columns, _ := app.db.getColumns(table) identityCols, _ := app.db.getIdentityColumns(strings.Split(table, ".")[2]) form := container.New(layout.NewFormLayout()) for _, val := range columns { form.Add(widget.NewLabel(val)) entry := widget.NewEntry() form.Add(entry) for _, identity := range identityCols { if identity == val { entry.PlaceHolder = "Данная колонка является автозаполняемой" entry.Disable() } } } form.Refresh() insertBtn := widget.NewButton("Вставить", func() { var insertColumns, insertValues []string for i := 0; i < len(form.Objects); i += 2 { column := form.Objects[i].(*widget.Label).Text isIdentity := false for _, identity := range identityCols { if identity == column { isIdentity = true break } } if isIdentity { continue } insertColumns = append(insertColumns, column) insertValues = append(insertValues, form.Objects[i+1].(*widget.Entry).Text) } err := app.db.insertIntoTable(table, insertColumns, insertValues) if err != nil { dialog.ShowInformation( "Вставка", err.Error(), app.window) return } dialog.ShowInformation( "Вставка", "Вставка выполнена успешно", app.window) }) backBtn := widget.NewButton("Назад", func() { app.showAdminTable(table) }) app.window.SetContent( genMainView( container.NewVScroll(form), []fyne.CanvasObject{insertBtn, backBtn})) } func (app *DBInterface) deleteAdminView(table string) { app.window.SetTitle(fmt.Sprintf("Удаление из таблицы [%s] (Режим администратора)", table)) columns, _ := app.db.getColumns(table) queryBox := container.NewVBox() newConstraintBtn := widget.NewButton("Добавить новое ограничение", func() { selectBtn := widget.NewSelect(columns, func(value string) {}) operatorBtn := widget.NewSelect([]string{"=", "<", ">", "<=", ">=", "LIKE"}, func(value string) {}) compareField := widget.NewEntry() fieldConstraint := container.NewGridWithColumns(3, selectBtn, operatorBtn, compareField) queryBox.Add(fieldConstraint) queryBox.Refresh() }) deleteBtn := widget.NewButton("Выполнить удаление", func() { if len(queryBox.Objects) == 0 { dialog.ShowInformation( "Удаление", "Необходимо указать как минимум одно ограничение", app.window) } else { query, err := parseQuery(queryBox) if err != nil { dialog.ShowInformation( "Удаление", err.Error(), app.window) return } err = app.db.deleteWhere(table, query) if err != nil { dialog.ShowInformation( "Удаление", err.Error(), app.window) return } dialog.ShowInformation( "Удаление", "Удаление выполнено успешно", app.window) } }) backBtn := widget.NewButton("Назад", func() { app.showAdminTable(table) }) app.window.SetContent( genMainView( container.NewVScroll( container.NewVBox( widget.NewLabel(fmt.Sprintf("DELETE FROM [%s] WHERE", table)), queryBox, newConstraintBtn)), []fyne.CanvasObject{deleteBtn, backBtn})) } func (app *DBInterface) selectAdminView(table string) { app.window.SetTitle(fmt.Sprintf("Выбор из таблицы [%s] (Режим администратора)", table)) columns, _ := app.db.getColumns(table) var selectFields []fyne.CanvasObject newField := widget.NewButton("Добавить новое поле", func() {}) var query []fyne.CanvasObject newConstraintBtn := widget.NewButton("Добавить новое ограничение", func() {}) updateView := func() { var widgets []fyne.CanvasObject widgets = append(widgets, widget.NewLabel("SELECT")) for _, val := range selectFields { widgets = append(widgets, container.NewHBox(val, widget.NewLabel(","))) } widgets = append(widgets, newField) widgets = append(widgets, widget.NewLabel(fmt.Sprintf("FROM [%s] WHERE", table))) for _, val := range query { widgets = append(widgets, val) } widgets = append(widgets, newConstraintBtn) selectBtn := widget.NewButton("Показать результаты выбора", func() { w := app.application.NewWindow("hello") w.Resize(fyne.NewSize(100, 100)) //conn := DBInterface{app.application, w, app.db} w.Show() }) backBtn := widget.NewButton("Назад", func() { app.showAdminTable(table) }) app.window.SetContent( genMainView( container.NewVScroll(container.NewVBox(widgets...)), []fyne.CanvasObject{selectBtn, backBtn})) } newField.OnTapped = func() { selectBtn := widget.NewSelect(columns, func(value string) { fmt.Println("Select set to", value) }) selectFields = append(selectFields, selectBtn) updateView() } newConstraintBtn.OnTapped = func() { selectBtn := widget.NewSelect(columns, func(value string) { fmt.Println("Select set to", value) }) operatorBtn := widget.NewSelect([]string{"=", "<", ">", "<=", ">=", "LIKE"}, func(value string) { fmt.Println("Select set to", value) }) compareField := widget.NewEntry() fieldConstraint := container.NewGridWithColumns(3, selectBtn, operatorBtn, compareField) query = append(query, fieldConstraint) updateView() } updateView() } func (app *DBInterface) oneToManyShowAdmin(manyTable string, manyColumn string, oneValue string) { app.window.SetTitle("Отношение один ко многим (Режим администратора)") data, err := app.db.getOneToManyTable(manyTable, manyColumn, oneValue) if err != nil { fmt.Println(err) return } columns, err := app.db.getColumns(manyTable) tableWidget := widget.NewTable( func() (int, int) { return len(data) + 1, len(columns) }, func() fyne.CanvasObject { return widget.NewLabel("some very wide content") }, func(i widget.TableCellID, o fyne.CanvasObject) { if i.Row == 0 { o.(*widget.Label).Alignment = fyne.TextAlignCenter o.(*widget.Label).TextStyle = fyne.TextStyle{Bold: true} o.(*widget.Label).SetText(fmt.Sprintf("%v", columns[i.Col])) } else { o.(*widget.Label).Alignment = fyne.TextAlignLeading o.(*widget.Label).TextStyle = fyne.TextStyle{Bold: false} o.(*widget.Label).SetText(fmt.Sprintf("%v", data[i.Row-1][i.Col])) } }) app.window.SetContent(container.NewMax(tableWidget)) } func (app *DBInterface) oneToManyParamsAdmin(table string, row int) { app.window.SetTitle("Выбор параметров отношения один ко многим (Режим администратора)") app.window.Resize(fyne.NewSize(720, 480)) oneColumns, _ := app.db.getColumns(table) tables, _ := app.db.getTables() data, _ := app.db.getTable(table) oneColumn := "" manyTable := "" manyColumn := "" oneValue := "" showTable := widget.NewButton("Показать таблицу", func() { app.oneToManyShowAdmin(manyTable, manyColumn, oneValue) }) showTable.Disable() manyFieldSelect := widget.NewSelect([]string{}, func(manyColumnVal string) { manyColumn = manyColumnVal showTable.Enable() }) manyFieldSelect.Disable() manyTablesSelect := widget.NewSelect(tables, func(manyTableVal string) { manyTable = manyTableVal manyColumns, _ := app.db.getColumns(manyTable) manyFieldSelect.Options = manyColumns manyFieldSelect.Refresh() manyFieldSelect.Enable() }) manyTablesSelect.Disable() selectedLabel := widget.NewLabel("") oneFieldSelect := widget.NewSelect(oneColumns, func(oneColumnVal string) { oneColumn = oneColumnVal columnIdx := 0 for i, val := range oneColumns { if val == oneColumn { columnIdx = i } } oneValue = fmt.Sprintf("%v", data[row][columnIdx]) selectedLabel.Text = fmt.Sprintf( "Значение [%s] выбранной строки = %v", oneColumn, oneValue) selectedLabel.Refresh() manyTablesSelect.Enable() }) app.window.SetContent( container.NewVBox( widget.NewLabel(fmt.Sprintf("Выбранная таблица: [%s]", table)), container.NewHBox(widget.NewLabel("Представитель связи \"один\":"), oneFieldSelect), selectedLabel, container.NewHBox(widget.NewLabel("Таблица связи \"многие\":"), manyTablesSelect), container.NewHBox(widget.NewLabel("Представитель связи \"многие\":"), manyFieldSelect), showTable)) } func (app *DBInterface) showAdminTable(table string) { app.window.SetTitle(fmt.Sprintf("Таблица [%s] (Режим администратора)", table)) data, err := app.db.getTable(table) if err != nil { fmt.Println(err) return } columns, err := app.db.getColumns(table) tableWidget := widget.NewTable( func() (int, int) { return len(data) + 1, len(columns) }, func() fyne.CanvasObject { return widget.NewLabel("some very wide content") }, func(i widget.TableCellID, o fyne.CanvasObject) { if i.Row == 0 { o.(*widget.Label).Alignment = fyne.TextAlignCenter o.(*widget.Label).TextStyle = fyne.TextStyle{Bold: true} o.(*widget.Label).SetText(fmt.Sprintf("%v", columns[i.Col])) } else { o.(*widget.Label).Alignment = fyne.TextAlignLeading o.(*widget.Label).TextStyle = fyne.TextStyle{Bold: false} o.(*widget.Label).SetText(fmt.Sprintf("%v", data[i.Row-1][i.Col])) } }) selectedRow := -1 tableWidget.OnSelected = func(id widget.TableCellID) { selectedRow = id.Row - 1 } selectBtn := widget.NewButton("Выбрать", func() { app.selectAdminView(table) }) insertBtn := widget.NewButton("Вставить", func() { app.insertAdminView(table) }) deleteBtn := widget.NewButton("Удалить", func() { app.deleteAdminView(table) }) oneToMany := widget.NewButton("Один ко многим", func() { if selectedRow == -1 { dialog.ShowInformation( "Один ко многим", "Не выбрана ни одна строка в таблице", app.window) } else { w := app.application.NewWindow("") w.Resize(fyne.NewSize(100, 100)) conn := DBInterface{app.application, w, app.db} conn.oneToManyParamsAdmin(table, selectedRow) w.Show() } }) back := widget.NewButton("Назад", func() { app.adminView() }) app.window.SetContent( genMainView( tableWidget, []fyne.CanvasObject{selectBtn, insertBtn, deleteBtn, oneToMany, back})) } func (app *DBInterface) adminView() { app.window.SetTitle("Режим администратора") tables, _ := app.db.getTables() var tableBtns []fyne.CanvasObject tableBtns = append(tableBtns, container.NewCenter(widget.NewLabel("Таблицы"))) for _, val := range tables { e := val tableBtns = append( tableBtns, widget.NewButton( fmt.Sprintf("Показать %s", val), func() { app.showAdminTable(e) })) } views, _ := app.db.getViews() var viewsBtns []fyne.CanvasObject viewsBtns = append(viewsBtns, container.NewCenter(widget.NewLabel("Представления"))) for _, val := range views { e := val viewsBtns = append( viewsBtns, widget.NewButton( fmt.Sprintf("Показать %s", val), func() { app.showAdminTable(e) })) } tablesScroll := container.NewVScroll(container.NewVBox(tableBtns...)) viewsScroll := container.NewVScroll(container.NewVBox(viewsBtns...)) dataBox := container.NewGridWithColumns(2, tablesScroll, viewsScroll) menuBtn := widget.NewButton("В меню", func() { app.menu() }) app.window.SetContent(genMainView(dataBox, []fyne.CanvasObject{menuBtn})) } func (app *DBInterface) showUserTable(table string) { data, err := app.db.getTable(table) if err != nil { fmt.Println(err) return } columns, err := app.db.getColumns(table) list := widget.NewTable( func() (int, int) { return len(data), len(columns) }, func() fyne.CanvasObject { return widget.NewLabel("wide content") }, func(i widget.TableCellID, o fyne.CanvasObject) { o.(*widget.Label).SetText(fmt.Sprintf("%v", data[i.Row][i.Col])) }) back := widget.NewButton("Назад", func() { app.userView() }) app.window.SetContent(genMainView(list, []fyne.CanvasObject{back})) } func (app *DBInterface) userView() { views, _ := app.db.getViews() var viewsBtns []fyne.CanvasObject viewsBtns = append(viewsBtns, container.NewCenter(widget.NewLabel("Представления"))) for _, val := range views { e := val viewsBtns = append( viewsBtns, widget.NewButton( fmt.Sprintf("Показать %s", val), func() { app.showUserTable(e) })) } viewsScroll := container.NewVScroll(container.NewVBox(viewsBtns...)) menuBtn := widget.NewButton("В меню", func() { app.menu() }) app.window.SetContent(container.NewBorder(nil, menuBtn, nil, nil, viewsScroll)) } func (app *DBInterface) menu() { app.window.SetTitle("Главное меню") app.window.SetContent(container.NewCenter( container.NewVBox( widget.NewButton("Режим Администратора", func() { app.adminView() }), widget.NewButton("Режим Пользователя", func() { app.userView() }), ), )) } func main() { myApp := app.New() window := myApp.NewWindow("Table Widget") window.Resize(fyne.NewSize(700, 480)) db := SQLConnection{} err := db.init() if err != nil { fmt.Println(err) return } dbApp := DBInterface{myApp, window, db} dbApp.menu() window.ShowAndRun() }