From 99a689996f5b125a8269582447a223b03d3c3051 Mon Sep 17 00:00:00 2001 From: mappu Date: Sat, 28 Sep 2024 14:27:19 +1200 Subject: [PATCH] uic: deeper implementation, add uidesigner example --- .gitignore | 2 + cmd/miqt-uic/constructors.go | 166 +++++++++++++++++ cmd/miqt-uic/ui2go.go | 173 +++++++++++++----- cmd/miqt-uic/uic_test.go | 2 +- cmd/miqt-uic/util.go | 11 ++ examples/uidesigner/design.go | 149 +++++++++++++++ .../uidesigner/design.ui | 0 examples/uidesigner/main.go | 20 ++ 8 files changed, 480 insertions(+), 43 deletions(-) create mode 100644 cmd/miqt-uic/constructors.go create mode 100644 examples/uidesigner/design.go rename cmd/miqt-uic/testdata/fixture1.ui => examples/uidesigner/design.ui (100%) create mode 100644 examples/uidesigner/main.go diff --git a/.gitignore b/.gitignore index 4b46cd8..67be7fe 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ examples/mdoutliner/mdoutliner examples/mdoutliner/mdoutliner.exe examples/windowsmanifest/windowsmanifest examples/windowsmanifest/windowsmanifest.exe +examples/uidesigner/uidesigner +examples/uidesigner/uidesigner.exe # android temporary build files android-build diff --git a/cmd/miqt-uic/constructors.go b/cmd/miqt-uic/constructors.go new file mode 100644 index 0000000..312a10e --- /dev/null +++ b/cmd/miqt-uic/constructors.go @@ -0,0 +1,166 @@ +package main + +func constructorFunctionFor(className string) (string, bool) { + + // Rebuild this list via: + // grep -PRoh 'func New.+\(parent \*QWidget\)' ~/dev/miqt/qt/ | sed -re 's~^func New([^0-9]+)([0-9]*)\(.*~case "\1": return "New\1\2", true~' + + switch className { + + // CODEGENERATED LIST START + + case "QListWidget": + return "NewQListWidget2", true + case "QAbstractSpinBox": + return "NewQAbstractSpinBox2", true + case "QStackedLayout": + return "NewQStackedLayout2", true + case "QColumnView": + return "NewQColumnView2", true + case "QProgressDialog": + return "NewQProgressDialog3", true + case "QTabWidget": + return "NewQTabWidget2", true + case "QLabel": + return "NewQLabel3", true + case "QKeySequenceEdit": + return "NewQKeySequenceEdit3", true + case "QDockWidget": + return "NewQDockWidget5", true + case "QFontComboBox": + return "NewQFontComboBox2", true + case "QTreeView": + return "NewQTreeView2", true + case "QCalendarWidget": + return "NewQCalendarWidget2", true + case "QLineEdit": + return "NewQLineEdit3", true + case "QMenuBar": + return "NewQMenuBar2", true + case "QFrame": + return "NewQFrame2", true + case "QAbstractScrollArea": + return "NewQAbstractScrollArea2", true + case "QSplitter": + return "NewQSplitter3", true + case "QStackedWidget": + return "NewQStackedWidget2", true + case "QWizard": + return "NewQWizard2", true + case "QWizardPage": + return "NewQWizardPage2", true + case "QMdiSubWindow": + return "NewQMdiSubWindow2", true + case "QStatusBar": + return "NewQStatusBar2", true + case "QToolButton": + return "NewQToolButton2", true + case "QShortcut": + return "NewQShortcut", true + case "QSlider": + return "NewQSlider3", true + case "QComboBox": + return "NewQComboBox2", true + case "QScrollBar": + return "NewQScrollBar3", true + case "QTabBar": + return "NewQTabBar2", true + case "QTextBrowser": + return "NewQTextBrowser2", true + case "QTreeWidget": + return "NewQTreeWidget2", true + case "QDialog": + return "NewQDialog2", true + case "QFormLayout": + return "NewQFormLayout2", true + case "QToolBar": + return "NewQToolBar4", true + case "QWidget": + return "NewQWidget2", true + case "QRadioButton": + return "NewQRadioButton3", true + case "QCheckBox": + return "NewQCheckBox3", true + case "QSizeGrip": + return "NewQSizeGrip", true + case "QLCDNumber": + return "NewQLCDNumber3", true + case "QFileDialog": + return "NewQFileDialog3", true + case "QUndoView": + return "NewQUndoView4", true + case "QGraphicsView": + return "NewQGraphicsView3", true + case "QPushButton": + return "NewQPushButton4", true + case "QColorDialog": + return "NewQColorDialog3", true + case "QMessageBox": + return "NewQMessageBox4", true + case "QSplashScreen": + return "NewQSplashScreen3", true + case "QErrorMessage": + return "NewQErrorMessage2", true + case "QListView": + return "NewQListView2", true + case "QDateTimeEdit": + return "NewQDateTimeEdit5", true + case "QTimeEdit": + return "NewQTimeEdit3", true + case "QDateEdit": + return "NewQDateEdit3", true + case "QMenu": + return "NewQMenu3", true + case "QToolBox": + return "NewQToolBox2", true + case "QTableWidget": + return "NewQTableWidget3", true + case "QFocusFrame": + return "NewQFocusFrame2", true + case "QHBoxLayout": + return "NewQHBoxLayout2", true + case "QVBoxLayout": + return "NewQVBoxLayout2", true + case "QInputDialog": + return "NewQInputDialog2", true + case "QTableView": + return "NewQTableView2", true + case "QMdiArea": + return "NewQMdiArea2", true + case "QSpinBox": + return "NewQSpinBox2", true + case "QDoubleSpinBox": + return "NewQDoubleSpinBox2", true + case "QProgressBar": + return "NewQProgressBar2", true + case "QTextEdit": + return "NewQTextEdit3", true + case "QAbstractSlider": + return "NewQAbstractSlider2", true + case "QDialogButtonBox": + return "NewQDialogButtonBox5", true + case "QFontDialog": + return "NewQFontDialog3", true + case "QMainWindow": + return "NewQMainWindow2", true + case "QCommandLinkButton": + return "NewQCommandLinkButton4", true + case "QDial": + return "NewQDial2", true + case "QGridLayout": + return "NewQGridLayout", true + case "QPlainTextEdit": + return "NewQPlainTextEdit3", true + case "QScrollArea": + return "NewQScrollArea2", true + case "QGroupBox": + return "NewQGroupBox3", true + + // CODEGENERATED LIST END + + default: + return "", false + + } + +} diff --git a/cmd/miqt-uic/ui2go.go b/cmd/miqt-uic/ui2go.go index 0eaae20..b7b9dc4 100644 --- a/cmd/miqt-uic/ui2go.go +++ b/cmd/miqt-uic/ui2go.go @@ -27,18 +27,34 @@ func collectClassNames_Widget(u UiWidget) []string { return ret } -func generateString(s *UiString, parentName string) string { - if s.Notr || parentName == "" { +func generateString(s *UiString, parentClass string) string { + if s.Notr || parentClass == "" { return strconv.Quote(s.Value) } - return parentName + `.Tr(` + strconv.Quote(s.Value) + `)` + return `qt.` + parentClass + `_Tr(` + strconv.Quote(s.Value) + `)` } -func generateWidget(w UiWidget, parentName string) (string, error) { +// qwidgetName creates the T.QWidget name that MIQT needs to access the base class. +func qwidgetName(name string, class string) string { + if name == "" { + return "nil" + } + if class == "QWidget" { + return name // It's already the right type + } + return name + ".QWidget" +} + +func generateWidget(w UiWidget, parentName string, parentClass string) (string, error) { ret := strings.Builder{} + ctor, ok := constructorFunctionFor(w.Class) + if !ok { + return "", fmt.Errorf("No known constructor function for %q class %q", w.Name, w.Class) + } + ret.WriteString(` - ui.` + w.Name + ` = qt.New` + w.Class + `(` + parentName + `) + ui.` + w.Name + ` = qt.` + ctor + `(` + qwidgetName(parentName, parentClass) + `) ui.` + w.Name + `.SetObjectName(` + strconv.Quote(w.Name) + `) `) @@ -59,7 +75,7 @@ func generateWidget(w UiWidget, parentName string) (string, error) { } else if prop.StringVal != nil { // "windowTitle", "title", "text" - ret.WriteString(`ui.` + w.Name + setterFunc + `(` + generateString(prop.StringVal, parentName) + ")\n") + ret.WriteString(`ui.` + w.Name + setterFunc + `(` + generateString(prop.StringVal, parentClass) + ")\n") } else if prop.EnumVal != nil { // "frameShape" @@ -70,10 +86,19 @@ func generateWidget(w UiWidget, parentName string) (string, error) { } } + // Attributes + // TODO + // w.Attributes + // Layout if w.Layout != nil { + ctor, ok := constructorFunctionFor(w.Layout.Class) + if !ok { + return "", fmt.Errorf("No known constructor function for %q class %q", w.Layout.Name, w.Layout.Class) + } + ret.WriteString(` - ui.` + w.Layout.Name + ` = qt.New` + w.Layout.Class + `(` + w.Name + `) + ui.` + w.Layout.Name + ` = qt.` + ctor + `(` + qwidgetName("ui."+w.Name, w.Class) + `) ui.` + w.Layout.Name + `.SetObjectName(` + strconv.Quote(w.Layout.Name) + `) `) @@ -82,7 +107,7 @@ func generateWidget(w UiWidget, parentName string) (string, error) { // Layout items have the parent as the real QWidget parent and are // separately assigned to the layout afterwards - nest, err := generateWidget(child.Widget, `ui.`+w.Name+`.QWidget`) // MIQT uses .QWidget to cast down + nest, err := generateWidget(child.Widget, `ui.`+w.Name, w.Class) if err != nil { return "", fmt.Errorf(w.Name+": %w", err) } @@ -97,9 +122,9 @@ func generateWidget(w UiWidget, parentName string) (string, error) { rowPos := fmt.Sprintf("%d", *child.Row) var colPos string if *child.Column == 0 { - colPos = `qt.QFormLayout__LabelRow` + colPos = `qt.QFormLayout__LabelRole` } else if *child.Column == 1 { - colPos = `qt.QFormLayout__FieldRow` + colPos = `qt.QFormLayout__FieldRole` } else { ret.WriteString("/* miqt-uic: QFormLayout does not understand column index */\n") continue @@ -107,15 +132,21 @@ func generateWidget(w UiWidget, parentName string) (string, error) { // For QFormLayout it's SetWidget ret.WriteString(` - ui.` + w.Layout.Name + `.SetWidget(` + rowPos + `, ` + colPos + `, ui.` + child.Widget.Name + `) + ui.` + w.Layout.Name + `.SetWidget(` + rowPos + `, ` + colPos + `, ` + qwidgetName(`ui.`+child.Widget.Name, child.Widget.Class) + `) `) case `QGridLayout`: - // For QGridLayout it's AddWidget + // For QGridLayout it's AddWidget2 // FIXME in Miqt this function has optionals, needs to be called with the correct arity // TODO support rowSpan, columnSpan ret.WriteString(` - ui.` + w.Layout.Name + `.AddWidget(ui.` + child.Widget.Name + `, ` + fmt.Sprintf("%d, %d", *child.Row, *child.Column) + `) + ui.` + w.Layout.Name + `.AddWidget2(` + qwidgetName(`ui.`+child.Widget.Name, child.Widget.Class) + `, ` + fmt.Sprintf("%d, %d", *child.Row, *child.Column) + `) + `) + + case "QVBoxLayout", "QHBoxLayout": + // For box layout it's AddWidget + ret.WriteString(` + ui.` + w.Layout.Name + `.AddWidget(` + qwidgetName(`ui.`+child.Widget.Name, child.Widget.Class) + `) `) default: @@ -132,32 +163,43 @@ func generateWidget(w UiWidget, parentName string) (string, error) { ui.` + a.Name + ` = qt.NewQAction(` + parentName + `) ui.` + a.Name + `.SetObjectName(` + strconv.Quote(a.Name) + `) `) - } - // AddActions - // TODO - // w.AddActions + // QActions are translated in the parent window's context + if prop, ok := propertyByName(a.Properties, "text"); ok { + ret.WriteString("ui." + a.Name + `.SetText(` + generateString(prop.StringVal, w.Class) + `)` + "\n") + } + + if prop, ok := propertyByName(a.Properties, "shortcut"); ok { + ret.WriteString("ui." + a.Name + `.SetShortcut(qt.NewQKeySequence2(` + generateString(prop.StringVal, w.Class) + `))` + "\n") + } + } // Items - for _, itm := range w.Items { - // FIXME add details - _ = itm - ret.WriteString("ui." + w.Name + `.AddItem()` + "\n") - } + for itemNo, itm := range w.Items { + ret.WriteString("ui." + w.Name + `.AddItem("")` + "\n") - // Attributes - // TODO - // w.Attributes + // Check for a "text" property and update the item's text + // Do this as a 2nd step so that the SetItemText can be trapped for retranslateUi() + // TODO Abstract for all SetItem{Foo} properties + if prop, ok := propertyByName(itm.Properties, "text"); ok { + ret.WriteString("ui." + w.Name + `.SetItemText(` + fmt.Sprintf("%d", itemNo) + `, ` + generateString(prop.StringVal, w.Class) + `)` + "\n") + } + } // Columns // TODO // w.Columns // Recurse children - setCentralWidget := "" + var ( + setCentralWidget = false + setMenuBar = false + setStatusBar = false + ) + for _, child := range w.Widgets { - nest, err := generateWidget(child, `ui.`+w.Name) + nest, err := generateWidget(child, `ui.`+w.Name, w.Class) if err != nil { return "", fmt.Errorf(w.Name+": %w", err) } @@ -167,9 +209,53 @@ func generateWidget(w UiWidget, parentName string) (string, error) { // QMainWindow CentralWidget handling // The first listed class can be the central widget. // TODO should it be the first child with a layout? But need to handle windows with no layout - if w.Class == `QMainWindow` && setCentralWidget == "" { + if w.Class == `QMainWindow` && !setCentralWidget { ret.WriteString(`ui.` + w.Name + `.SetCentralWidget(ui.` + child.Name + ") // Set central widget \n") - setCentralWidget = w.Name + setCentralWidget = true + } + + // QDockWidget also has something like a central widget + if w.Class == `QDockWidget` && !setCentralWidget { + ret.WriteString(`ui.` + w.Name + `.SetWidget(ui.` + child.Name + ") // Set central widget \n") + setCentralWidget = true + } + + if w.Class == "QMainWindow" && child.Class == "QMenuBar" && !setMenuBar { + ret.WriteString(`ui.` + w.Name + `.SetMenuBar(ui.` + child.Name + `)` + "\n") + setMenuBar = true + } + if w.Class == "QMainWindow" && child.Class == "QStatusBar" && !setStatusBar { + ret.WriteString(`ui.` + w.Name + `.SetStatusBar(ui.` + child.Name + `)` + "\n") + setStatusBar = true + } + + // QTabWidget->QTab handling + if w.Class == `QTabWidget` { + ret.WriteString(`ui.` + w.Name + `.AddTab(` + qwidgetName(`ui.`+child.Name, child.Class) + `, "")` + "\n") + } + } + + // AddActions + // n.b. This must be *after* all children have been constructed, in case we + // are adding a direct child + + for _, a := range w.AddActions { + if a.Name == "separator" { + // TODO how does Qt Designer disambiguate a real QAction with name="separator" ? + ret.WriteString("ui." + w.Name + ".AddSeparator()\n") + + } else { + // If we are a menubar, then refers to top-level QMenu instead of QAction + if w.Class == "QMenuBar" { + ret.WriteString("ui." + w.Name + ".AddMenu(ui." + a.Name + ")\n") + } else if w.Class == "QMenu" { + // QMenu has its own .AddAction() implementation that takes plain string + // That's convenient, but it shadows the AddAction version that takes a QAction* + // We need to use the underlying QWidget.AddAction explicitly + ret.WriteString("ui." + w.Name + ".QWidget.AddAction(ui." + a.Name + ")\n") + } else { + ret.WriteString("ui." + w.Name + ".AddAction(ui." + a.Name + ")\n") + } } } @@ -186,7 +272,7 @@ func generate(packageName string, goGenerateArgs string, u UiFile) ([]byte, erro package ` + packageName + ` import ( - "github.com/mappu/miqt" + "github.com/mappu/miqt/qt" ) type ` + u.Class + `Ui struct { @@ -198,28 +284,31 @@ func New` + u.Class + `Ui() *` + u.Class + `Ui { ui := &` + u.Class + `Ui{} `) - nest, err := generateWidget(u.Widget, "") + nest, err := generateWidget(u.Widget, "", "") if err != nil { return nil, err } - ret.WriteString(nest) - ret.WriteString(` - return ui -} - -// RetranslateUi reapplies all text translations. -func (u *` + u.Class + `Ui) RetranslateUi() { - `) - - // Trap and repeat all lines from `.nest` that include .Tr(. + // Don't emit any of the lines that included .Tr(), move them into the + // retranslateUi() function + var translateFunc []string for _, line := range strings.Split(nest, "\n") { - if strings.Contains(line, `.Tr(`) { + if strings.Contains(line, `_Tr(`) { + translateFunc = append(translateFunc, line) + } else { ret.WriteString(line + "\n") } } ret.WriteString(` + ui.Retranslate() + + return ui +} + +// Retranslate reapplies all text translations. +func (ui *` + u.Class + `Ui) Retranslate() { + ` + strings.Join(translateFunc, "\n") + ` } `) diff --git a/cmd/miqt-uic/uic_test.go b/cmd/miqt-uic/uic_test.go index d6bb3b9..289e1d7 100644 --- a/cmd/miqt-uic/uic_test.go +++ b/cmd/miqt-uic/uic_test.go @@ -43,5 +43,5 @@ func TestFixtureMarshalRoundtrip(t *testing.T) { } - testFixture("testdata/fixture1.ui") + testFixture("../../examples/uidesigner/design.ui") } diff --git a/cmd/miqt-uic/util.go b/cmd/miqt-uic/util.go index 9375dc2..e35c86b 100644 --- a/cmd/miqt-uic/util.go +++ b/cmd/miqt-uic/util.go @@ -71,3 +71,14 @@ func xmlConvertToSelfClosing(input string) string { return strings.Join(lines, "\n") } + +// propertyByName searches a slice of UiProperty to find one with a matching name. +func propertyByName(check []UiProperty, search string) (UiProperty, bool) { + for _, p := range check { + if p.Name == search { + return p, true + } + } + + return UiProperty{}, false +} diff --git a/examples/uidesigner/design.go b/examples/uidesigner/design.go new file mode 100644 index 0000000..8d60c2e --- /dev/null +++ b/examples/uidesigner/design.go @@ -0,0 +1,149 @@ +// Generated by miqt-uic. To update this file, edit the .ui file in +// Qt Designer, and then run 'go generate'. +// +//go:generate miqt-uic -InFile design.ui -OutFile design.go + +package main + +import ( + "github.com/mappu/miqt/qt" +) + +type MainWindowUi struct { + MainWindow *qt.QMainWindow + centralwidget *qt.QWidget + gridLayout *qt.QGridLayout + tabWidget *qt.QTabWidget + tab *qt.QWidget + formLayout *qt.QFormLayout + label *qt.QLabel + comboBox *qt.QComboBox + label_2 *qt.QLabel + spinBox *qt.QSpinBox + tab_2 *qt.QWidget + treeWidget *qt.QTreeWidget + menubar *qt.QMenuBar + menu_File *qt.QMenu + statusbar *qt.QStatusBar + dockWidget *qt.QDockWidget + dockWidgetContents *qt.QWidget + verticalLayout *qt.QVBoxLayout + calendarWidget *qt.QCalendarWidget + action_New *qt.QAction + actionE_xit *qt.QAction +} + +// NewMainWindowUi creates all Qt widget classes for MainWindow. +func NewMainWindowUi() *MainWindowUi { + ui := &MainWindowUi{} + + ui.MainWindow = qt.NewQMainWindow2(nil) + ui.MainWindow.SetObjectName("MainWindow") + ui.MainWindow.Resize(800, 600) + ui.MainWindow.SetWindowTitle("MainWindow") + + ui.action_New = qt.NewQAction() + ui.action_New.SetObjectName("action_New") + + ui.actionE_xit = qt.NewQAction() + ui.actionE_xit.SetObjectName("actionE_xit") + + ui.centralwidget = qt.NewQWidget2(ui.MainWindow.QWidget) + ui.centralwidget.SetObjectName("centralwidget") + + ui.gridLayout = qt.NewQGridLayout(ui.centralwidget) + ui.gridLayout.SetObjectName("gridLayout") + + ui.tabWidget = qt.NewQTabWidget2(ui.centralwidget) + ui.tabWidget.SetObjectName("tabWidget") + + ui.tab = qt.NewQWidget2(ui.tabWidget.QWidget) + ui.tab.SetObjectName("tab") + + ui.formLayout = qt.NewQFormLayout2(ui.tab) + ui.formLayout.SetObjectName("formLayout") + + ui.label = qt.NewQLabel3(ui.tab) + ui.label.SetObjectName("label") + + ui.formLayout.SetWidget(0, qt.QFormLayout__LabelRole, ui.label.QWidget) + + ui.comboBox = qt.NewQComboBox2(ui.tab) + ui.comboBox.SetObjectName("comboBox") + ui.comboBox.AddItem("") + ui.comboBox.AddItem("") + + ui.formLayout.SetWidget(0, qt.QFormLayout__FieldRole, ui.comboBox.QWidget) + + ui.label_2 = qt.NewQLabel3(ui.tab) + ui.label_2.SetObjectName("label_2") + + ui.formLayout.SetWidget(1, qt.QFormLayout__LabelRole, ui.label_2.QWidget) + + ui.spinBox = qt.NewQSpinBox2(ui.tab) + ui.spinBox.SetObjectName("spinBox") + + ui.formLayout.SetWidget(1, qt.QFormLayout__FieldRole, ui.spinBox.QWidget) + ui.tabWidget.AddTab(ui.tab, "") + + ui.tab_2 = qt.NewQWidget2(ui.tabWidget.QWidget) + ui.tab_2.SetObjectName("tab_2") + ui.tabWidget.AddTab(ui.tab_2, "") + + ui.gridLayout.AddWidget2(ui.tabWidget.QWidget, 0, 0) + + ui.treeWidget = qt.NewQTreeWidget2(ui.centralwidget) + ui.treeWidget.SetObjectName("treeWidget") + ui.treeWidget.SetFrameShape(qt.QFrame__Panel) + + ui.gridLayout.AddWidget2(ui.treeWidget.QWidget, 0, 1) + ui.MainWindow.SetCentralWidget(ui.centralwidget) // Set central widget + + ui.menubar = qt.NewQMenuBar2(ui.MainWindow.QWidget) + ui.menubar.SetObjectName("menubar") + ui.menubar.Resize(800, 29) + + ui.menu_File = qt.NewQMenu3(ui.menubar.QWidget) + ui.menu_File.SetObjectName("menu_File") + ui.menu_File.QWidget.AddAction(ui.action_New) + ui.menu_File.AddSeparator() + ui.menu_File.QWidget.AddAction(ui.actionE_xit) + ui.menubar.AddMenu(ui.menu_File) + ui.MainWindow.SetMenuBar(ui.menubar) + + ui.statusbar = qt.NewQStatusBar2(ui.MainWindow.QWidget) + ui.statusbar.SetObjectName("statusbar") + ui.MainWindow.SetStatusBar(ui.statusbar) + + ui.dockWidget = qt.NewQDockWidget5(ui.MainWindow.QWidget) + ui.dockWidget.SetObjectName("dockWidget") + + ui.dockWidgetContents = qt.NewQWidget2(ui.dockWidget.QWidget) + ui.dockWidgetContents.SetObjectName("dockWidgetContents") + + ui.verticalLayout = qt.NewQVBoxLayout2(ui.dockWidgetContents) + ui.verticalLayout.SetObjectName("verticalLayout") + + ui.calendarWidget = qt.NewQCalendarWidget2(ui.dockWidgetContents) + ui.calendarWidget.SetObjectName("calendarWidget") + + ui.verticalLayout.AddWidget(ui.calendarWidget.QWidget) + ui.dockWidget.SetWidget(ui.dockWidgetContents) // Set central widget + + ui.Retranslate() + + return ui +} + +// Retranslate reapplies all text translations. +func (ui *MainWindowUi) Retranslate() { + ui.action_New.SetText(qt.QMainWindow_Tr("&New...")) + ui.actionE_xit.SetText(qt.QMainWindow_Tr("E&xit")) + ui.actionE_xit.SetShortcut(qt.NewQKeySequence2(qt.QMainWindow_Tr("Ctrl+Q"))) + ui.label.SetText(qt.QWidget_Tr("Dropdown:")) + ui.comboBox.SetItemText(0, qt.QComboBox_Tr("First")) + ui.comboBox.SetItemText(1, qt.QComboBox_Tr("Second")) + ui.label_2.SetText(qt.QWidget_Tr("Number:")) + ui.menu_File.SetTitle(qt.QMenuBar_Tr("&File")) + ui.dockWidget.SetWindowTitle(qt.QMainWindow_Tr("Dock Title")) +} diff --git a/cmd/miqt-uic/testdata/fixture1.ui b/examples/uidesigner/design.ui similarity index 100% rename from cmd/miqt-uic/testdata/fixture1.ui rename to examples/uidesigner/design.ui diff --git a/examples/uidesigner/main.go b/examples/uidesigner/main.go new file mode 100644 index 0000000..3bad42e --- /dev/null +++ b/examples/uidesigner/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + "os" + + "github.com/mappu/miqt/qt" +) + +func main() { + + qt.NewQApplication(os.Args) + + ui := NewMainWindowUi() + ui.MainWindow.Show() + + qt.QApplication_Exec() + + fmt.Println("OK!") +}