mirror of
https://github.com/mappu/miqt.git
synced 2024-12-22 08:58:37 +00:00
examples/mdoutliner: use go:embed, support multiple tabs
This commit is contained in:
parent
b282701af9
commit
04692b78f8
8
examples/mdoutliner/README.md
Normal file
8
examples/mdoutliner/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Markdown Outliner
|
||||||
|
|
||||||
|
This is sample markdown content.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- You can use the outline on the left to jump to parts of the document
|
||||||
|
- Demonstrates use of the MIQT library
|
@ -1,30 +1,62 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mappu/miqt/qt"
|
"github.com/mappu/miqt/qt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const sampleContent = `# Markdown Outliner
|
//go:embed README.md
|
||||||
|
var embedContent embed.FS
|
||||||
|
|
||||||
This is sample markdown content.
|
const (
|
||||||
|
lineNumberRole = int(qt.ItemDataRole__UserRole + 1)
|
||||||
## Features
|
)
|
||||||
|
|
||||||
- You can use the outline on the left to jump to parts of the document
|
|
||||||
- Demonstrates use of the MIQT library`
|
|
||||||
|
|
||||||
type AppWindow struct {
|
type AppWindow struct {
|
||||||
w *qt.QMainWindow
|
w *qt.QMainWindow
|
||||||
cw *qt.QWidget
|
cw *qt.QWidget
|
||||||
|
|
||||||
|
tabs *qt.QTabWidget
|
||||||
|
tabData []AppTab
|
||||||
|
}
|
||||||
|
|
||||||
|
type AppTab struct {
|
||||||
|
tab *qt.QWidget
|
||||||
outline *qt.QListWidget
|
outline *qt.QListWidget
|
||||||
textArea *qt.QTextEdit
|
textArea *qt.QTextEdit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewAppTab() *AppTab {
|
||||||
|
var ret AppTab
|
||||||
|
|
||||||
|
tab := qt.NewQWidget()
|
||||||
|
ret.tab = tab
|
||||||
|
|
||||||
|
layout := qt.NewQHBoxLayout2(tab)
|
||||||
|
|
||||||
|
panes := qt.NewQSplitter()
|
||||||
|
layout.AddWidget(panes.QWidget)
|
||||||
|
|
||||||
|
ret.outline = qt.NewQListWidget2(tab)
|
||||||
|
panes.AddWidget(ret.outline.QWidget)
|
||||||
|
ret.outline.OnCurrentItemChanged(ret.handleJumpToBookmark)
|
||||||
|
|
||||||
|
ret.textArea = qt.NewQTextEdit3(tab)
|
||||||
|
ret.textArea.OnTextChanged(ret.handleTextChanged)
|
||||||
|
|
||||||
|
panes.AddWidget(ret.textArea.QWidget)
|
||||||
|
|
||||||
|
panes.SetSizes([]int{250, 550})
|
||||||
|
|
||||||
|
return &ret
|
||||||
|
}
|
||||||
|
|
||||||
func NewAppWindow() *AppWindow {
|
func NewAppWindow() *AppWindow {
|
||||||
|
|
||||||
ret := AppWindow{}
|
ret := AppWindow{}
|
||||||
@ -36,6 +68,14 @@ func NewAppWindow() *AppWindow {
|
|||||||
|
|
||||||
mnu := qt.NewQMenuBar()
|
mnu := qt.NewQMenuBar()
|
||||||
fileMenu := mnu.AddMenuWithTitle("&File")
|
fileMenu := mnu.AddMenuWithTitle("&File")
|
||||||
|
|
||||||
|
newtab := fileMenu.AddAction("New Tab")
|
||||||
|
newtab.SetShortcut(qt.NewQKeySequence2("Ctrl+N"))
|
||||||
|
newtab.SetIcon(qt.QIcon_FromTheme("document-new"))
|
||||||
|
newtab.OnTriggered1(func() {
|
||||||
|
ret.createTabWithContents("New Document", "")
|
||||||
|
})
|
||||||
|
|
||||||
open := fileMenu.AddAction("Open...")
|
open := fileMenu.AddAction("Open...")
|
||||||
open.SetShortcut(qt.NewQKeySequence2("Ctrl+O"))
|
open.SetShortcut(qt.NewQKeySequence2("Ctrl+O"))
|
||||||
open.SetIcon(qt.QIcon_FromTheme("document-open"))
|
open.SetIcon(qt.QIcon_FromTheme("document-open"))
|
||||||
@ -59,29 +99,20 @@ func NewAppWindow() *AppWindow {
|
|||||||
|
|
||||||
// Main widgets
|
// Main widgets
|
||||||
|
|
||||||
ret.cw = qt.NewQWidget2(ret.w.QWidget)
|
ret.tabs = qt.NewQTabWidget2(ret.w.QWidget)
|
||||||
ret.w.SetCentralWidget(ret.cw)
|
ret.w.SetCentralWidget(ret.tabs.QWidget)
|
||||||
layout := qt.NewQHBoxLayout2(ret.cw)
|
|
||||||
|
|
||||||
panes := qt.NewQSplitter()
|
// Add initial tab
|
||||||
layout.AddWidget(panes.QWidget)
|
|
||||||
|
|
||||||
ret.outline = qt.NewQListWidget2(ret.cw)
|
sampleContent, err := embedContent.ReadFile("README.md")
|
||||||
panes.AddWidget(ret.outline.QWidget)
|
if err != nil {
|
||||||
ret.outline.OnCurrentItemChanged(ret.handleJumpToBookmark)
|
panic(err)
|
||||||
|
}
|
||||||
ret.textArea = qt.NewQTextEdit3(ret.cw)
|
ret.createTabWithContents("README.md", string(sampleContent))
|
||||||
ret.textArea.OnTextChanged(ret.handleTextChanged)
|
|
||||||
ret.textArea.SetText(sampleContent)
|
|
||||||
panes.AddWidget(ret.textArea.QWidget)
|
|
||||||
|
|
||||||
panes.SetSizes([]int{250, 550})
|
|
||||||
|
|
||||||
return &ret
|
return &ret
|
||||||
}
|
}
|
||||||
|
|
||||||
const lineNumberRole = int(qt.ItemDataRole__UserRole + 1)
|
|
||||||
|
|
||||||
func (a *AppWindow) handleFileOpen() {
|
func (a *AppWindow) handleFileOpen() {
|
||||||
fname := qt.QFileDialog_GetOpenFileName4(a.w.QWidget, "Open markdown file...", "", "Markdown files (*.md *.txt);;All Files (*)")
|
fname := qt.QFileDialog_GetOpenFileName4(a.w.QWidget, "Open markdown file...", "", "Markdown files (*.md *.txt);;All Files (*)")
|
||||||
if fname == "" {
|
if fname == "" {
|
||||||
@ -94,41 +125,50 @@ func (a *AppWindow) handleFileOpen() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
a.textArea.SetText(string(contents))
|
a.createTabWithContents(filepath.Base(fname), string(contents))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppWindow) handleTextChanged() {
|
func (a *AppWindow) createTabWithContents(tabTitle, tabContent string) {
|
||||||
content := a.textArea.ToPlainText()
|
|
||||||
a.updateOutlineForContent(content)
|
tab := NewAppTab()
|
||||||
|
tab.textArea.SetText(tabContent)
|
||||||
|
|
||||||
|
tabIdx := a.tabs.AddTab2(tab.tab, qt.QIcon_FromTheme("text-markdown"), tabTitle)
|
||||||
|
a.tabs.SetCurrentIndex(tabIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppWindow) updateOutlineForContent(content string) {
|
func (t *AppTab) handleTextChanged() {
|
||||||
a.outline.Clear()
|
content := t.textArea.ToPlainText()
|
||||||
|
t.updateOutlineForContent(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *AppTab) updateOutlineForContent(content string) {
|
||||||
|
t.outline.Clear()
|
||||||
|
|
||||||
lines := strings.Split(content, "\n")
|
lines := strings.Split(content, "\n")
|
||||||
|
|
||||||
for lineNumber, line := range lines {
|
for lineNumber, line := range lines {
|
||||||
if strings.HasPrefix(line, `#`) {
|
if strings.HasPrefix(line, `#`) {
|
||||||
|
|
||||||
bookmark := qt.NewQListWidgetItem7(line, a.outline)
|
bookmark := qt.NewQListWidgetItem7(line, t.outline)
|
||||||
bookmark.SetToolTip(fmt.Sprintf("Line %d", lineNumber+1))
|
bookmark.SetToolTip(fmt.Sprintf("Line %d", lineNumber+1))
|
||||||
bookmark.SetData(lineNumberRole, qt.NewQVariant5(lineNumber))
|
bookmark.SetData(lineNumberRole, qt.NewQVariant5(lineNumber))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppWindow) handleJumpToBookmark() {
|
func (t *AppTab) handleJumpToBookmark() {
|
||||||
itm := a.outline.CurrentItem()
|
itm := t.outline.CurrentItem()
|
||||||
if itm == nil {
|
if itm == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lineNumber := itm.Data(lineNumberRole).ToInt()
|
lineNumber := itm.Data(lineNumberRole).ToInt()
|
||||||
|
|
||||||
targetBlock := a.textArea.Document().FindBlockByLineNumber(lineNumber)
|
targetBlock := t.textArea.Document().FindBlockByLineNumber(lineNumber)
|
||||||
a.textArea.SetTextCursor(qt.NewQTextCursor4(targetBlock))
|
t.textArea.SetTextCursor(qt.NewQTextCursor4(targetBlock))
|
||||||
|
|
||||||
a.textArea.SetFocus()
|
t.textArea.SetFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user