加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
gui.go 51.33 KB
一键复制 编辑 原始数据 按行查看 历史
rocket049 提交于 2023-02-13 11:02 . 编辑区加边框
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"time"
"github.com/skratchdot/open-golang/open"
"github.com/therecipe/qt/gui"
"github.com/therecipe/qt/printsupport"
"github.com/rocket049/gettext-go/gettext"
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/widgets"
)
var datDir string
func init() {
exe1, _ := os.Executable()
dir1 := path.Dir(exe1)
locale1 := path.Join(dir1, "locale")
gettext.BindTextdomain("sdiary", locale1, nil)
gettext.Textdomain("sdiary")
home1, _ := os.UserHomeDir()
cfg := path.Join(home1, ".sdiary", "datapath.txt")
cfgBytes, err := ioutil.ReadFile(cfg)
if err != nil {
datDir = path.Join(home1, ".sdiary")
} else {
datDir = string(cfgBytes)
}
}
type diaryPointer struct {
Item *gui.QStandardItem
Id int
Day string
YearMonth string
//Modified bool
}
func (s *diaryPointer) zero() {
s.Item = nil
s.Id = 0
s.Day = ""
s.YearMonth = ""
}
//T wrap gettext.T
func T(v string) string {
return gettext.T(v)
}
type formatData struct {
BF *gui.QTextBlockFormat
CF *gui.QTextCharFormat
}
type myWindow struct {
app *widgets.QApplication
window *widgets.QMainWindow
tree *widgets.QTreeView
model *gui.QStandardItemModel
treeFind *widgets.QTreeView
modelFind *gui.QStandardItemModel
editor *widgets.QTextEdit
comboAttachs *widgets.QComboBox
actionTextBold *widgets.QAction
actionTextUnderline *widgets.QAction
actionTextItalic *widgets.QAction
actionStrikeOut *widgets.QAction
exportEnc *widgets.QAction
exportPdf *widgets.QAction
exportOdt *widgets.QAction
importEnc *widgets.QAction
changeStorage *widgets.QAction
paste *widgets.QAction
search *widgets.QAction
replace *widgets.QAction
lineMargin *widgets.QAction
searchInput *widgets.QLineEdit
replaceInput *widgets.QLineEdit
newDiary *widgets.QAction
saveDiary *widgets.QAction
renDiary *widgets.QAction
modifyPwd *widgets.QAction
fb *widgets.QAction //格式刷
categories *widgets.QMenu
category int
categoryName string
categoryItem *widgets.QAction
curDiary *diaryPointer
user string
key []byte
db *myDb
document qtextFormat
format formatData
}
func (s *myWindow) getNewId() (res int) {
return s.db.NextId()
}
func (s *myWindow) setMenuBar() {
s.document.Images = make(map[string][]byte)
menubar := s.window.MenuBar()
menu := menubar.AddMenu2(T("File"))
s.exportEnc = menu.AddAction(T("Export Encrypted Diary"))
s.exportEnc.SetDisabled(true)
s.exportEnc.ConnectTriggered(func(b bool) {
s.saveCurDiary()
s.exportEncryptedDiary()
})
s.exportPdf = menu.AddAction(T("Export PDF..."))
s.exportPdf.SetDisabled(true)
s.exportPdf.ConnectTriggered(func(b bool) {
s.exportAsPdf()
})
s.exportOdt = menu.AddAction(T("Export Odt..."))
s.exportOdt.SetDisabled(true)
s.exportOdt.ConnectTriggered(func(b bool) {
s.exportAsOdt()
})
s.importEnc = menu.AddAction(T("Import Encrypted Diary"))
s.importEnc.ConnectTriggered(func(b bool) {
s.importEncryptedDiary()
})
exportAll := menu.AddAction((T("Export All")))
exportAll.ConnectTriggered(func(b bool) {
home, _ := os.UserHomeDir()
dir := widgets.QFileDialog_GetExistingDirectory(s.window, T("Select export directory"), home, 0)
if len(dir) == 0 {
return
}
fromDir := filepath.Join(datDir, s.user)
toFile := filepath.Join(home, s.user+".bak")
err := zipData(fromDir, toFile)
if err != nil {
widgets.QMessageBox_About(s.window, T("Error"), err.Error())
} else {
widgets.QMessageBox_About(s.window, T("Complete"), T("Complete"))
}
})
importAll := menu.AddAction(T("Import All"))
importAll.ConnectTriggered(func(b bool) {
home, _ := os.UserHomeDir()
filename := widgets.QFileDialog_GetOpenFileName(s.window, T("Select a bakup file"), home, ".bak (*.bak)", ".bak (*.bak)", 0)
if len(filename) == 0 {
return
}
var ok bool
pwd := widgets.QInputDialog_GetText(s.window, T("The password of the bakup file"), T("Password:"), widgets.QLineEdit__Password, "",
&ok, core.Qt__Dialog, core.Qt__ImhNone)
if len(filename) < 4 || !ok {
return
}
err := s.importFromZip(filename, pwd)
if err != nil {
widgets.QMessageBox_About(s.window, T("Error"), err.Error())
} else {
widgets.QMessageBox_About(s.window, T("Complete"), T("Complete"))
}
s.clearModel()
s.addYearMonthsFromDb()
})
s.changeStorage = menu.AddAction(T("Change Storage Dir"))
s.changeStorage.ConnectTriggered(func(b bool) {
dir1 := widgets.QFileDialog_GetExistingDirectory(s.window, T("Select Storage Directory"), datDir, 0)
if len(dir1) > 0 {
home1, _ := os.UserHomeDir()
cfg := path.Join(home1, ".sdiary", "datapath.txt")
ioutil.WriteFile(cfg, []byte(dir1), 0644)
widgets.QMessageBox_Information(s.window, T("Quit program"),
T("The program will terminate now.")+"\n"+T("How to move data?")+"\n"+T("Move the directories to the new directory from ")+datDir,
widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
s.app.Quit()
}
})
menu = menubar.AddMenu2(T("Edit"))
s.paste = menu.AddAction(T("Paste Text"))
s.paste.SetShortcut(gui.QKeySequence_FromString("Ctrl+d", gui.QKeySequence__NativeText))
s.paste.ConnectTriggered(func(b bool) {
s.pasteText()
})
s.search = menu.AddAction(T("Search"))
s.search.SetShortcut(gui.QKeySequence_FromString("Ctrl+f", gui.QKeySequence__NativeText))
s.search.ConnectTriggered(func(b bool) {
s.findText()
})
s.replace = menu.AddAction(T("Replace"))
s.replace.SetShortcut(gui.QKeySequence_FromString("Ctrl+r", gui.QKeySequence__NativeText))
s.replace.ConnectTriggered(func(b bool) {
s.replaceText()
})
s.lineMargin = menu.AddAction(T("Top Margin"))
s.lineMargin.SetShortcut(gui.QKeySequence_FromString("Ctrl+l", gui.QKeySequence__NativeText))
s.lineMargin.ConnectTriggered(func(b bool) {
s.changeLineMargin()
})
menu = menubar.AddMenu2(T("Table"))
newTable := menu.AddAction(T("Insert Table"))
newTable.ConnectTriggered(func(b bool) {
s.insertTable()
})
addPreRow := menu.AddAction(T("Insert Row"))
addPreRow.ConnectTriggered(func(b bool) {
t, c := s.getTable()
if t == nil {
return
}
t.InsertRows(c.Row(), 1)
})
appendRow := menu.AddAction(T("Append Row"))
appendRow.ConnectTriggered(func(b bool) {
t, _ := s.getTable()
if t == nil {
return
}
t.AppendRows(1)
})
addPreCol := menu.AddAction(T("Insert Column"))
addPreCol.ConnectTriggered(func(b bool) {
t, c := s.getTable()
if t == nil {
return
}
t.InsertColumns(c.Column(), 1)
})
appendCol := menu.AddAction(T("Append Column"))
appendCol.ConnectTriggered(func(b bool) {
t, _ := s.getTable()
if t == nil {
return
}
t.AppendColumns(1)
})
removeRow := menu.AddAction(T("Remove Row"))
removeRow.ConnectTriggered(func(b bool) {
t, c := s.getTable()
if t == nil {
return
}
t.RemoveRows(c.Row(), 1)
})
removeCol := menu.AddAction(T("Remove Column"))
removeCol.ConnectTriggered(func(b bool) {
t, c := s.getTable()
if t == nil {
return
}
t.RemoveColumns(c.Column(), 1)
})
s.showCategores(menubar)
menu = menubar.AddMenu2(T("Manage"))
s.renDiary = menu.AddAction(T("Rename"))
s.renDiary.ConnectTriggered(func(b bool) {
s.rename()
})
s.modifyPwd = menu.AddAction(T("ModifyPassword"))
s.modifyPwd.ConnectTriggered(func(b bool) {
s.updatePwd()
})
menu = menubar.AddMenu2(T("Help"))
about := menu.AddAction(T("About"))
about.ConnectTriggered(func(b bool) {
s.showMsg(T("About"), T("Copy Right: Fu Huizhong <fuhuizn@163.com>\nSecurity Diary ")+version+"\n"+T("Crypto with AES256")+"\nHomepage: https://github.com/rocket049/secret-diary")
})
update1 := menu.AddAction(T("Update"))
update1.ConnectTriggered(func(b bool) {
v, newest := versionCheck()
if newest == true {
s.showMsg(T("Update"), T("This is the Newest Version!"))
} else {
s.showMsg(T("Update"), T("Current:")+version+"\n"+T("Newest:")+v+"\n"+T("I will open the page on github website after you click button 'OK'!"))
open.Start("https://github.com/rocket049/secret-diary/releases")
}
})
itemName := "Add To Menu"
if runtime.GOOS == "windows" {
itemName = "Create Desktop Shortcut"
}
add2menu := menu.AddAction(T(itemName))
add2menu.ConnectTriggered(func(b bool) {
makeShortcut(true)
if runtime.GOOS == "linux" {
s.showMsg(T("Add To Menu"), T("You can start this program from 'Start'->'Office'"))
}
})
bak := menu.AddAction(T("Backup & Delete"))
bak.ConnectTriggered(func(b bool) {
s.showMsg(T("Backup & Delete"), T("Your DATA Storage path is '")+dataDir+"'\n"+T("You can backup and delete the directory yourself."))
})
pwd := menu.AddAction(T("Password"))
pwd.ConnectTriggered(func(b bool) {
s.showMsg(T("Password"), T("There is no way to recover password. \nPlease write it on paper!"))
})
support := menu.AddAction(T("Support Author"))
support.ConnectTriggered(func(b bool) {
s.showPay()
})
}
func (s *myWindow) setToolBar() {
bar := widgets.NewQToolBar("File", nil)
var icon *gui.QIcon
icon = gui.NewQIcon5(":/qml/icons/document-new.jpg")
s.newDiary = bar.AddAction2(icon, T("New"))
s.newDiary.ConnectTriggered(func(b bool) {
s.setStatusBar(T("New Diary"))
now := time.Now()
s.addDiary(now.Format("2006-01"), now.Format("02"), T("New Diary")+now.Format("2006-01-02"))
})
icon = gui.NewQIcon5(":/qml/icons/document-save.jpg")
s.saveDiary = bar.AddAction2(icon, T("Save"))
s.saveDiary.SetToolTip(T("Save") + " Ctrl-S")
s.saveDiary.SetShortcut(gui.QKeySequence_FromString("CTRL+s", gui.QKeySequence__NativeText))
s.window.AddToolBar2(bar)
bar = widgets.NewQToolBar("Format", nil)
icon = gui.NewQIcon5(":/qml/icons/h1.png")
head1 := bar.AddAction2(icon, "H1")
head1.SetToolTip(T("Header 1"))
head1.ConnectTriggered(func(b bool) {
s.setHeader(1)
})
icon = gui.NewQIcon5(":/qml/icons/h2.png")
head2 := bar.AddAction2(icon, "H2")
head2.SetToolTip(T("Header 2"))
head2.ConnectTriggered(func(b bool) {
s.setHeader(2)
})
icon = gui.NewQIcon5(":/qml/icons/h3.png")
head3 := bar.AddAction2(icon, "H3")
head3.SetToolTip(T("Header 3"))
head3.ConnectTriggered(func(b bool) {
s.setHeader(3)
})
icon = gui.NewQIcon5(":/qml/icons/std.png")
standard := bar.AddAction2(icon, T("Standard"))
standard.ConnectTriggered(func(b bool) {
var cfmt = gui.NewQTextCharFormat()
cfmt.SetFont2(s.app.Font())
cfmt.SetFontPointSize(14)
cfmt.SetForeground(gui.NewQBrush3(gui.NewQColor2(core.Qt__black), core.Qt__SolidPattern))
s.mergeFormatOnLineOrSelection(cfmt)
})
//var icon *gui.QIcon
icon = gui.NewQIcon5(":/qml/icons/B.png")
s.actionTextBold = bar.AddAction2(icon, T("Bold"))
s.actionTextBold.SetCheckable(true)
s.actionTextBold.ConnectTriggered(func(checked bool) {
s.textBold()
})
icon = gui.NewQIcon5(":/qml/icons/I.png")
s.actionTextItalic = bar.AddAction2(icon, T("Italic"))
s.actionTextItalic.SetCheckable(true)
s.actionTextItalic.ConnectTriggered(func(checked bool) {
s.textItalic()
})
icon = gui.NewQIcon5(":/qml/icons/U.png")
s.actionTextUnderline = bar.AddAction2(icon, T("Underline"))
s.actionTextUnderline.SetCheckable(true)
s.actionTextUnderline.ConnectTriggered(func(checked bool) {
s.textUnderline()
})
icon = gui.NewQIcon5(":/qml/icons/S.png")
s.actionStrikeOut = bar.AddAction2(icon, T("StrikeOut"))
s.actionStrikeOut.SetCheckable(true)
s.actionStrikeOut.ConnectTriggered(func(checked bool) {
s.textStrikeOut()
})
icon = gui.NewQIcon5(":/qml/icons/fg.png")
actionTextColor := bar.AddAction2(icon, T("Text Color..."))
actionTextColor.ConnectTriggered(func(checked bool) {
s.textColor()
})
icon = gui.NewQIcon5(":/qml/icons/bg.png")
actionBgColor := bar.AddAction2(icon, T("Background Color..."))
actionBgColor.ConnectTriggered(func(checked bool) {
s.textBgColor()
})
icon = gui.NewQIcon5(":/qml/icons/draw-eraser.png")
actionClear := bar.AddAction2(icon, T("Clear Line Format..."))
actionClear.ConnectTriggered(func(checked bool) {
s.clearFormatAtCursor()
})
s.addJustifyActions(bar)
icon = gui.NewQIcon5(":/qml/icons/right.png")
increaseIdent := bar.AddAction2(icon, T("Increase Ident"))
increaseIdent.ConnectTriggered(func(checked bool) {
s.addIndent(1)
})
icon = gui.NewQIcon5(":/qml/icons/left.png")
degreeIdent := bar.AddAction2(icon, T("Decrease Ident"))
degreeIdent.ConnectTriggered(func(checked bool) {
s.addIndent(-1)
})
icon = gui.NewQIcon5(":/qml/icons/brush.png")
s.fb = bar.AddAction2(icon, T("Format Brush"))
s.fb.SetCheckable(true)
s.fb.ConnectTriggered(func(checked bool) {
cursor := s.editor.TextCursor()
if !cursor.HasSelection() {
cursor.Select(gui.QTextCursor__LineUnderCursor)
}
s.format.BF = cursor.BlockFormat()
s.format.CF = cursor.CharFormat()
s.fb.SetChecked(true)
})
comboStyle := widgets.NewQComboBox(bar)
bar.AddWidget(comboStyle)
comboStyle.AddItems([]string{
T("Standard"),
T("List (Disc)"),
T("List (Circle)"),
T("List (Square)"),
T("List (Decimal)"),
T("List (Alpha lower)"),
T("List (Alpha upper)"),
T("List (Roman lower)"),
T("List (Roman upper)"),
})
comboStyle.ConnectActivated(s.textStyle)
s.window.AddToolBar2(bar)
bar = widgets.NewQToolBar("Insert", nil)
addImage := bar.AddAction(T("Insert Image"))
addImage.SetToolTip(T("Insert Image"))
addImage.ConnectTriggered(func(b bool) {
s.insertImage()
})
addTable := bar.AddAction(T("Insert Table"))
addTable.SetToolTip(T("Insert Table"))
addTable.ConnectTriggered(func(b bool) {
s.insertTable()
})
attach := bar.AddAction(T("Attach..."))
attach.SetToolTip(T("Append Attachments"))
attach.ConnectTriggered(func(b bool) {
filename := widgets.QFileDialog_GetOpenFileName(s.window, T("Seclect File"), ".", "All (*)", "All (*)", widgets.QFileDialog__ReadOnly)
if s.addAttachment(filename) {
s.showAttachList()
s.editor.Document().SetModified(true)
//curDiary.Modified = true
}
})
font := bar.AddAction(T("Font"))
font.SetToolTip(T("CurrentFont"))
font.ConnectTriggered(func(b bool) {
var ok bool
f := widgets.QFontDialog_GetFont2(&ok, s.window)
if ok {
cfmt := gui.NewQTextCharFormat()
cfmt.SetFont2(f)
s.mergeFormatOnLineOrSelection(cfmt)
}
})
s.window.AddToolBar2(bar)
}
func (s *myWindow) setStatusBar(msg string) {
bar := s.window.StatusBar()
bar.ShowMessage(msg, 20000)
}
func (s *myWindow) setupComboAttachs() *widgets.QHBoxLayout {
hbox := widgets.NewQHBoxLayout()
s.comboAttachs = widgets.NewQComboBox(s.window)
s.comboAttachs.SetSizePolicy2(widgets.QSizePolicy__Expanding, widgets.QSizePolicy__Fixed)
list := []string{fmt.Sprintf("-- %s(%s:0) --", T("Select Attachments"), T("Total"))}
s.comboAttachs.AddItems(list)
expBtn := widgets.NewQPushButton2(T("Export As..."), s.window)
expBtn.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
hbox.AddWidget(s.comboAttachs, 1, 0)
hbox.AddWidget(expBtn, 1, 0)
delBtn := widgets.NewQPushButton2(T("Remove"), s.window)
delBtn.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Fixed)
hbox.AddWidget(delBtn, 1, 0)
expBtn.ConnectClicked(func(b bool) {
idx := s.comboAttachs.CurrentIndex()
if idx == 0 {
return
}
idx -= 1
dlg := widgets.NewQFileDialog(s.window, core.Qt__Dialog)
filename := dlg.GetSaveFileName(s.window, T("Save File"), s.document.Attachments[idx].Name, "All (*)", "All (*)", 0)
if len(filename) > 0 {
ioutil.WriteFile(filename, s.document.Attachments[idx].Data, 0644)
}
})
delBtn.ConnectClicked(func(b bool) {
if s.comboAttachs.CurrentIndex() == 0 {
return
}
ret := widgets.QMessageBox_Question(s.window, T("Remove"), T("Are you sure?"), widgets.QMessageBox__Yes|widgets.QMessageBox__No, widgets.QMessageBox__Yes)
if ret == widgets.QMessageBox__Yes {
s.removeCurAttachment()
}
})
return hbox
}
func (s *myWindow) showAttachList() {
list := []string{fmt.Sprintf("-- %s(%s:%d) --", T("Select Attachments"), T("Total"), len(s.document.Attachments))}
for _, v := range s.document.Attachments {
list = append(list, v.Name)
}
s.comboAttachs.Clear()
s.comboAttachs.AddItems(list)
}
func (s *myWindow) clearAttachs() {
s.comboAttachs.Clear()
list := []string{fmt.Sprintf("-- %s(%s:0) --", T("Select Attachments"), T("Total"))}
s.comboAttachs.AddItems(list)
}
func (s *myWindow) addAttachment(filename string) bool {
name := filepath.Base(filename)
data, err := ioutil.ReadFile(filename)
if err != nil {
log.Println(err)
return false
}
s.document.Attachments = append(s.document.Attachments, attachmentFile{Name: name, Data: data})
return true
}
func (s *myWindow) Create(app *widgets.QApplication) {
font := gui.NewQFont()
font.SetPointSize(12)
font.SetFamily("Serif")
font.SetStyleName("Regular")
app.SetFont(font, "serif-regular")
s.app = app
charW := s.charWidth()
s.window = widgets.NewQMainWindow(nil, core.Qt__Window)
s.window.SetWindowTitle(T("UserName"))
s.window.SetWindowIcon(gui.NewQIcon5(":/qml/icons/Sd.png"))
s.curDiary = new(diaryPointer)
spliter := widgets.NewQSplitter2(core.Qt__Horizontal, s.window)
s.window.SetCentralWidget(spliter)
leftArea := s.createLeftArea(charW)
spliter.AddWidget(leftArea)
editor := s.createEditor(charW)
spliter.AddWidget(editor)
spliter.SetStretchFactor(0, 1)
spliter.SetStretchFactor(1, 2)
s.setToolBar()
s.setMenuBar()
app.SetActiveWindow(s.window)
app.SetApplicationDisplayName(T("Secret Diary"))
app.SetApplicationName("sdiary")
app.SetApplicationVersion(version)
s.setEditorFuncs()
s.setTreeFuncs()
once := sync.Once{}
s.window.ConnectShowEvent(func(e *gui.QShowEvent) {
once.Do(func() {
go makeShortcut(false)
s.login()
})
})
s.window.ConnectCloseEvent(func(e *gui.QCloseEvent) {
if s.editor.Document().IsModified() {
ret := widgets.QMessageBox_Question(s.window, T("Close"), T("Do you want to save the document?"), widgets.QMessageBox__Yes|widgets.QMessageBox__No, widgets.QMessageBox__Yes)
if ret == widgets.QMessageBox__Yes {
s.saveCurDiary()
}
}
s.db.Close()
})
s.window.ShowMaximized()
}
func (s *myWindow) createLeftArea(charW int) widgets.QWidget_ITF {
spliter := widgets.NewQSplitter(nil)
spliter.SetOrientation(core.Qt__Vertical)
spliter.SetSizePolicy2(widgets.QSizePolicy__Preferred, widgets.QSizePolicy__Expanding)
//mwidth := charW * 18
s.tree = widgets.NewQTreeView(s.window)
//s.tree.SetMaximumWidth(mwidth)
s.tree.SetSizePolicy2(widgets.QSizePolicy__Preferred, widgets.QSizePolicy__Expanding)
s.tree.SetHorizontalScrollBarPolicy(core.Qt__ScrollBarAsNeeded)
s.tree.SetAutoScroll(true)
s.model = gui.NewQStandardItemModel2(0, 1, s.tree)
s.clearModel()
s.tree.SetModel(s.model)
spliter.AddWidget(s.tree)
search := widgets.NewQWidget(nil, core.Qt__Widget)
grid := newGridLayout(search)
keyword := widgets.NewQLineEdit(search)
grid.AddWidget2(keyword, 0, 0, 0)
btn := widgets.NewQPushButton2(T("Search"), search)
grid.AddWidget2(btn, 0, 1, 0)
btn.ConnectClicked(func(b bool) {
s.searchFromDb(strings.TrimSpace(keyword.Text()))
})
keyword.ConnectEditingFinished(func() {
s.searchFromDb(strings.TrimSpace(keyword.Text()))
})
s.treeFind = widgets.NewQTreeView(s.window)
s.treeFind.SetSizePolicy2(widgets.QSizePolicy__Preferred, widgets.QSizePolicy__Preferred)
s.treeFind.SetHorizontalScrollBarPolicy(core.Qt__ScrollBarAsNeeded)
s.treeFind.SetAutoScroll(true)
s.modelFind = gui.NewQStandardItemModel2(0, 1, s.treeFind)
s.clearModelFind()
s.treeFind.SetModel(s.modelFind)
grid.AddWidget3(s.treeFind, 1, 0, 1, 2, 0)
search.SetLayout(grid)
spliter.AddWidget(search)
s.setTreeFindFuncs()
return spliter
}
func (s *myWindow) createEditor(charW int) widgets.QWidget_ITF {
editorLayout := widgets.NewQVBoxLayout()
scrollarea := widgets.NewQScrollArea(s.window)
scrollarea.SetHorizontalScrollBarPolicy(core.Qt__ScrollBarAsNeeded)
scrollarea.SetVerticalScrollBarPolicy(core.Qt__ScrollBarAsNeeded)
scrollarea.SetAlignment(core.Qt__AlignCenter)
scrollarea.SetSizePolicy2(widgets.QSizePolicy__Expanding, widgets.QSizePolicy__Expanding)
frame := widgets.NewQFrame(s.window, core.Qt__Widget)
grid := newGridLayout(frame)
s.editor = widgets.NewQTextEdit(s.window)
s.editor.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Expanding)
s.editor.SetTabChangesFocus(false)
s.editor.SetReadOnly(true)
s.editor.SetStyleSheet("QTextEdit{background-color:rgba(255,255,255,255);border:1px;border-style:solid;border-color:#000000}")
width := charW * 30
s.editor.SetTabStopWidth(40)
s.editor.SetFixedWidth(width)
scrollarea.SetMinimumWidth(width + 40)
s.editor.SetSizePolicy2(widgets.QSizePolicy__Fixed, widgets.QSizePolicy__Expanding)
scrollarea.ConnectResizeEvent(func(e *gui.QResizeEvent) {
frame.SetFixedSize(core.NewQSize2(width+40, scrollarea.Geometry().Height()))
scrollarea.ActivateWindow()
})
grid.AddWidget2(s.editor, 0, 0, 0)
comboBox := s.setupComboAttachs()
//grid.AddLayout(comboBox, 1, 0, 0)
//grid.SetAlign(core.Qt__AlignHCenter)
frame.SetLayout(grid)
scrollarea.SetWidget(frame)
editorLayout.AddWidget(scrollarea, 1, 0)
editorLayout.AddLayout(comboBox, 1)
res := widgets.NewQWidget(s.window, core.Qt__Widget)
res.SetLayout(editorLayout)
return res
}
func (s *myWindow) saveCurDiary() {
if s.editor.Document().IsModified() == false {
s.setStatusBar(T("No Diary Saved"))
return
}
//fmt.Println("save", curDiary.Item.AccessibleText(), s.editor.ToHtml())
var first bool = false
if len(s.curDiary.Item.AccessibleText()) == 0 {
p := s.curDiary.Item.Parent()
pos := s.curDiary.Item.Index()
item := p.TakeChild(pos.Row(), pos.Column())
item.SetAccessibleText(fmt.Sprintf("%d", s.db.NextId()))
p.SetChild(pos.Row(), pos.Column(), item)
s.curDiary.Item = item
first = true
}
filename := s.curDiary.Item.AccessibleText() + ".dat"
id, err := strconv.Atoi(s.curDiary.Item.AccessibleText())
if err != nil {
s.setStatusBar(T("Error ID"))
return
}
vs := strings.SplitN(s.curDiary.Item.Text(), "-", 2)
title := vs[1]
//fmt.Println(filename, title)
if first {
s.db.AddDiary(id, time.Now().Format("2006-01-02"), title, filename)
} else {
s.db.UpdateDiaryTitle(id, title)
}
encodeToFile(s.getRichText(), filename, s.key)
s.setStatusBar(T("Save Diary") + fmt.Sprintf(" %s(%s)", title, filename))
s.editor.Document().SetModified(false)
}
func (s *myWindow) addDiary(yearMonth, day, title string) {
if s.curDiary.Item != nil {
s.saveCurDiary()
}
month := s.addYearMonth(yearMonth)
month.SetAccessibleText("1")
month.SetAccessibleDescription("1")
diary := gui.NewQStandardItem2(fmt.Sprintf("%s-%s", day, title))
diary.SetEditable(false)
diary.SetAccessibleText("")
diary.SetAccessibleDescription("0")
//month.AppendRow2(diary)
month.InsertRow2(0, diary)
s.tree.SetCurrentIndex(diary.Index())
s.curDiary.Item = diary
s.curDiary.Day = day
s.curDiary.YearMonth = yearMonth
s.document.Attachments = []attachmentFile{}
s.document.Images = make(map[string][]byte)
s.editor.SetReadOnly(false)
s.exportEnc.SetEnabled(true)
s.exportPdf.SetEnabled(true)
s.exportOdt.SetEnabled(true)
s.setTitle(title)
s.clearAttachs()
s.tree.Expand(month.Index())
}
func (s *myWindow) addDiary2(id, day, title, mtime string, r, c int) {
item := s.model.Item(r, c)
diary := gui.NewQStandardItem2(fmt.Sprintf("%s-%s", day, title))
diary.SetEditable(false)
diary.SetAccessibleText(id)
diary.SetAccessibleDescription("0")
diary.SetToolTip(T("Last Modified:") + mtime)
item.AppendRow2(diary)
}
func (s *myWindow) addYearMonthsFromDb() {
s.setStatusBar(T("Loading Diary List..."))
s.editor.Document().Clear()
s.editor.Document().SetModified(false)
s.editor.SetReadOnly(true)
s.curDiary.zero()
bridge := NewQmlBridge(s.window)
var wg sync.WaitGroup
bridge.ConnectAddYearMonth(func(ym string) {
s.addYearMonth(ym)
wg.Done()
})
bridge.ConnectAddDiary(func(id, day, title, mtime string, r, c int) {
item := s.model.Item(r, c)
diary := gui.NewQStandardItem2(fmt.Sprintf("%s-%s", day, title))
diary.SetEditable(false)
diary.SetAccessibleText(id)
diary.SetAccessibleDescription("0")
diary.SetToolTip(T("Last Modified:") + mtime)
item.AppendRow2(diary)
wg.Done()
})
bridge.ConnectSetMonthFlag(func(r, c int) {
item := s.model.TakeItem(r, c)
item.SetAccessibleText("1")
item.SetAccessibleDescription("1")
s.model.SetItem(r, c, item)
s.tree.ResizeColumnToContents(0)
if r < 2 {
s.tree.Expand(item.Index())
}
})
go func() {
yms, err := s.db.GetYearMonths()
if err != nil {
return
}
for i := 0; i < len(yms); i++ {
wg.Add(1)
bridge.AddYearMonth(yms[i])
}
wg.Wait()
pidx := s.tree.RootIndex()
for r := 0; r < s.model.RowCount(pidx); r++ {
if r > 2 {
break
}
c := 0
item := s.model.Item(r, c)
items, err := s.db.GetListFromYearMonth(item.Text())
if err != nil {
log.Println(err)
return
}
for i := 0; i < len(items); i++ {
wg.Add(1)
bridge.AddDiary(strconv.Itoa(items[i].Id), items[i].Day, items[i].Title, items[i].MTime, r, c)
}
wg.Wait()
bridge.SetMonthFlag(r, c)
}
}()
return
}
func (s *myWindow) setMonthFlag(r, c int) {
item := s.model.TakeItem(r, c)
item.SetAccessibleText("1")
item.SetAccessibleDescription("1")
s.model.SetItem(r, c, item)
s.tree.ResizeColumnToContents(0)
if r < 2 {
s.tree.Expand(item.Index())
}
}
func (s *myWindow) addYearMonth(yearMonth string) *gui.QStandardItem {
idx := core.NewQModelIndex()
p := s.model.Parent(idx)
n := s.model.RowCount(p)
for i := 0; i < n; i++ {
item := s.model.Item(i, 0)
if item.Text() == yearMonth {
return item
}
}
item := gui.NewQStandardItem2(yearMonth)
item.SetColumnCount(1)
item.SetEditable(false)
item.SetAccessibleText("")
s.model.InsertRow2(0, item)
return item
}
func (s *myWindow) selectDiary(idx *core.QModelIndex) {
diary := s.model.ItemFromIndex(idx)
if diary.Pointer() == s.curDiary.Item.Pointer() {
return
}
if len(diary.AccessibleText()) == 0 {
return
}
filename := diary.AccessibleText() + ".dat"
data, err := decodeFromFile(filename, s.key)
if err != nil {
//log.Println(err)
s.getQText(data)
if s.curDiary.Item != nil {
s.saveCurDiary()
}
s.curDiary.Item = diary
//curDiary.Modified = false
s.curDiary.YearMonth = diary.Parent().Text()
vs := strings.Index(diary.Text(), "-")
s.curDiary.Day = diary.Text()[:vs]
s.setTitle(diary.Text()[vs+1:])
} else {
if s.curDiary.Item != nil {
s.saveCurDiary()
}
s.getQText(data)
s.curDiary.Item = diary
//curDiary.Modified = false
s.curDiary.YearMonth = diary.Parent().Text()
vs := strings.Index(diary.Text(), "-")
s.curDiary.Day = diary.Text()[:vs]
s.editor.Document().SetHtml(s.document.Html)
s.showAttachList()
s.editor.Document().SetModified(false)
}
s.tree.SetCurrentIndex(diary.Index())
s.editor.SetReadOnly(false)
s.exportEnc.SetEnabled(true)
s.exportPdf.SetEnabled(true)
s.exportOdt.SetEnabled(true)
}
func (s *myWindow) popupOnMonth(item *gui.QStandardItem, point *core.QPoint) {
s.LockEditor()
menu := widgets.NewQMenu(s.tree)
refreshItem := menu.AddAction(T("Refresh"))
refreshItem.ConnectTriggered(func(checked bool) {
items, err := s.db.GetListFromYearMonth(item.Text())
idx := item.Index()
item.RemoveRows(0, item.RowCount())
r, c := idx.Row(), idx.Column()
if err != nil {
log.Println(err)
return
}
for i := 0; i < len(items); i++ {
id := strconv.Itoa(items[i].Id)
day := items[i].Day
title := items[i].Title
mtime := items[i].MTime
diary := gui.NewQStandardItem2(fmt.Sprintf("%s-%s", day, title))
diary.SetEditable(false)
diary.SetAccessibleText(id)
diary.SetAccessibleDescription("0")
diary.SetToolTip(T("Last Modified:") + mtime)
item.AppendRow2(diary)
}
s.setMonthFlag(r, c)
s.tree.Expand(idx)
})
menu.Popup(point, nil)
}
func (s *myWindow) diaryPopup(idx *core.QModelIndex, e *gui.QMouseEvent) {
//fmt.Println("popup")
diary := s.model.ItemFromIndex(s.tree.CurrentIndex())
switch diary.AccessibleDescription() {
case "0":
s.selectDiary(idx)
case "1":
s.popupOnMonth(diary, e.GlobalPos())
return
default:
return
}
menu := widgets.NewQMenu(s.tree)
delItem := menu.AddAction(T("Delete"))
delItem.ConnectTriggered(func(checked bool) {
dlg := widgets.NewQMessageBox(s.window)
dlg.SetWindowTitle(T("Confirm Delete"))
dlg.SetText(T("Are you sure?"))
dlg.SetIcon(widgets.QMessageBox__Question)
dlg.SetStandardButtons(widgets.QMessageBox__Yes | widgets.QMessageBox__Cancel)
ret := dlg.Exec()
if ret == int(widgets.QMessageBox__Yes) {
id := diary.AccessibleText()
if len(id) > 0 {
s.db.RemoveDiary(id)
}
s.curDiary.zero()
//curDiary.Modified = false
p := diary.Parent()
p.RemoveRow(diary.Row())
}
})
openItem := menu.AddAction(T("Open in New Window"))
openItem.ConnectTriggered(func(checked bool) {
id, err := strconv.Atoi(diary.AccessibleText())
if err != nil {
s.setStatusBar(err.Error())
return
}
OpenDiaryNewWindow(s, id)
})
category := menu.AddAction(T("Change Category"))
category.ConnectTriggered(func(checked bool) {
id, err := strconv.Atoi(diary.AccessibleText())
if err != nil {
s.setStatusBar(err.Error())
return
}
dict := s.db.GetCategories()
dict1 := make(map[string]int)
dict1[T("Default")] = 0
items := []string{T("Default")}
for k, v := range dict {
dict1[v] = k
items = append(items, v)
}
var ok bool
ret := widgets.QInputDialog_GetItem(s.window, T("Category"), T("Select a category"), items, 0, false, &ok, core.Qt__Dialog, 0)
if ok && dict1[ret] != s.category {
s.db.UpdateDiaryCategory(id, dict1[ret])
s.model.RemoveRow(diary.Row(), diary.Index().Parent())
}
})
menu.QWidget.AddAction(s.exportEnc)
menu.QWidget.AddAction(s.exportPdf)
menu.QWidget.AddAction(s.exportOdt)
menu.Popup(e.GlobalPos(), nil)
}
func (s *myWindow) LockEditor() {
s.saveCurDiary()
s.curDiary.zero()
s.editor.Clear()
s.editor.SetReadOnly(true)
s.editor.Document().SetModified(false)
}
func (s *myWindow) onSelectItem(idx *core.QModelIndex) {
item := s.model.ItemFromIndex(idx)
loadChildren := func() {
items, err := s.db.GetListFromYearMonth(item.Text())
r, c := idx.Row(), idx.Column()
if err != nil {
log.Println(err)
return
}
for i := 0; i < len(items); i++ {
s.addDiary2(strconv.Itoa(items[i].Id), items[i].Day, items[i].Title, items[i].MTime, r, c)
}
s.setMonthFlag(r, c)
//s.tree.Expand(idx)
}
//fmt.Println("AD:", item.AccessibleDescription())
switch item.AccessibleDescription() {
case "0":
s.selectDiary(idx)
case "1":
s.LockEditor()
if item.HasChildren() == false {
loadChildren()
} else {
s.tree.ClearSelection()
}
default:
loadChildren()
}
}
func (s *myWindow) CollapseOrExpand(idx *core.QModelIndex) {
item := s.model.ItemFromIndex(idx)
if item.AccessibleDescription() == "1" {
if s.tree.IsExpanded(idx) {
s.tree.Collapse(idx)
} else {
s.tree.Expand(idx)
}
}
}
var expandTime = time.Now()
func (s *myWindow) setTreeFuncs() {
s.tree.SetSelectionMode(widgets.QAbstractItemView__SingleSelection)
s.tree.DisconnectMousePressEvent()
s.tree.DisconnectMouseDoubleClickEvent()
s.tree.DisconnectMouseReleaseEvent()
s.tree.ConnectMouseReleaseEvent(func(e *gui.QMouseEvent) {
idx := s.tree.IndexAt(e.Pos())
if !idx.IsValid() {
return
}
s.tree.SetCurrentIndex(idx)
switch e.Button() {
case core.Qt__LeftButton:
if time.Now().After(expandTime.Add(time.Millisecond * 500)) {
expandTime = time.Now()
s.CollapseOrExpand(idx)
}
case core.Qt__RightButton:
s.diaryPopup(idx, e)
}
})
s.tree.ConnectExpanded(func(idx *core.QModelIndex) {
expandTime = time.Now()
})
s.tree.ConnectCollapsed(func(idx *core.QModelIndex) {
expandTime = time.Now()
})
s.tree.ConnectSelectionChanged(func(selected *core.QItemSelection, deselected *core.QItemSelection) {
idxes := selected.Indexes()
if len(idxes) == 1 {
s.onSelectItem(idxes[0])
}
})
}
func (s *myWindow) setTitle(v string) {
s.editor.Clear()
s.editor.Document().Clear()
var cfmt = gui.NewQTextCharFormat()
cfmt.SetFont2(s.app.Font())
cfmt.SetFontPointSize(18)
cfmt.SetForeground(gui.NewQBrush3(gui.NewQColor2(core.Qt__blue), core.Qt__SolidPattern))
s.editor.SetFontPointSize(18)
s.editor.SetAlignment(core.Qt__AlignCenter)
cursor := s.editor.TextCursor()
cursor.SetCharFormat(cfmt)
cursor.InsertText(v)
cursor.InsertText("\n")
s.editor.SetTextCursor(cursor)
var afmt = gui.NewQTextCharFormat()
afmt.SetForeground(gui.NewQBrush3(gui.NewQColor2(core.Qt__black), core.Qt__SolidPattern))
afmt.SetFont2(s.app.Font())
afmt.SetFontPointSize(14)
s.editor.SetAlignment(core.Qt__AlignLeft | core.Qt__AlignAbsolute)
cursor.InsertText("\n\t")
s.mergeFormatOnLineOrSelection(afmt)
s.editor.SetTextCursor(cursor)
}
func (s *myWindow) setEditorFuncs() {
s.saveDiary.ConnectTriggered(func(b bool) {
if s.model != nil {
s.saveCurDiary()
} else {
s.saveDiaryAlone()
}
})
if s.model != nil {
s.editor.ConnectTextChanged(s.OnTextChanged)
}
s.editor.ConnectContextMenuEvent(func(e *gui.QContextMenuEvent) {
menu := s.editor.CreateStandardContextMenu()
imgUrl := s.getSelectedImage()
if len(imgUrl) > 0 {
//addaction export image
act := menu.AddAction(T("Export Image As..."))
act.ConnectTriggered(func(b bool) {
ext := filepath.Ext(imgUrl)
filter := fmt.Sprintf("%s Image (*%s)", ext, ext)
filename := widgets.QFileDialog_GetSaveFileName(s.window, T("Export Image As..."), filepath.Base(imgUrl), filter, filter, 0)
if strings.HasSuffix(filename, ext) == false {
filename = filename + ext
}
if len(filename) > 0 {
ioutil.WriteFile(filename, s.document.Images[imgUrl], 0644)
}
})
actScale := menu.AddAction(T("Scale Image"))
actScale.ConnectTriggered(func(b bool) {
v := s.editor.Document().Resource(int(gui.QTextDocument__ImageResource), core.NewQUrl3(imgUrl, core.QUrl__TolerantMode))
img := gui.NewQImageFromPointer(v.ToImage())
res := s.scaleImage(img)
s.editor.Document().AddResource(int(gui.QTextDocument__ImageResource), core.NewQUrl3(imgUrl, core.QUrl__TolerantMode), res.ToVariant())
//save data
ba := core.NewQByteArray()
iod := core.NewQBuffer2(ba, nil)
iod.Open(core.QIODevice__WriteOnly)
ok := res.Save2(iod, filepath.Ext(filepath.Base(imgUrl))[1:], -1)
//fmt.Println(filepath.Ext(filename))
if ok {
s.document.Images[imgUrl] = []byte(ba.Data())
}
s.editor.Document().SetModified(true)
})
}
//add search
menu.QWidget.AddAction(s.paste)
menu.QWidget.AddAction(s.search)
menu.QWidget.AddAction(s.replace)
menu.QWidget.AddAction(s.lineMargin)
menu.Popup(e.GlobalPos(), nil)
})
s.editor.ConnectMouseReleaseEvent(func(e *gui.QMouseEvent) {
defer e.Accept()
if s.format.BF == nil {
return
}
cursor := s.editor.TextCursor()
if !cursor.HasSelection() {
cursor.Select(gui.QTextCursor__BlockUnderCursor)
}
cursor.SetBlockFormat(s.format.BF)
cursor.SetCharFormat(s.format.CF)
s.format.BF = nil
s.format.CF = nil
s.fb.SetChecked(false)
})
onEnterOrReturn := func() {
cursor := s.editor.TextCursor()
cursor.Select(gui.QTextCursor__BlockUnderCursor)
//fmt.Printf("B:%#v\n", cursor.SelectedText())
txt := cursor.SelectedText()
r1 := regexp.MustCompile("^(\t+).*$")
tabs := r1.FindStringSubmatch(strings.TrimLeft(txt, "\u2029"))
if len(tabs) > 1 {
s.editor.InsertPlainTextDefault("\n" + tabs[1])
} else {
s.editor.InsertPlainTextDefault("\n")
}
}
s.editor.ConnectKeyPressEvent(func(e *gui.QKeyEvent) {
switch core.Qt__Key(e.Key()) {
case core.Qt__Key_Enter:
onEnterOrReturn()
case core.Qt__Key_Return:
onEnterOrReturn()
default:
s.editor.KeyPressEventDefault(e)
}
})
}
func (s *myWindow) OnTextChanged() {
if s.curDiary.Item == nil {
return
}
disp1 := s.curDiary.Day + "-" + strings.TrimSpace(s.editor.Document().FirstBlock().Text())
disp0 := s.curDiary.Item.Text()
if disp0 != disp1 {
p := s.curDiary.Item.Parent()
pos := s.curDiary.Item.Index()
s.curDiary.Item = p.TakeChild(pos.Row(), pos.Column())
s.curDiary.Item.SetText(disp1)
p.SetChild(pos.Row(), pos.Column(), s.curDiary.Item)
s.tree.SetCurrentIndex(s.curDiary.Item.Index())
s.tree.ResizeColumnToContents(0)
if s.editor.CurrentCharFormat().FontPointSize() != 18 {
var cfmt = gui.NewQTextCharFormat()
cfmt.SetFont2(s.app.Font())
cfmt.SetFontPointSize(18)
cfmt.SetForeground(gui.NewQBrush3(gui.NewQColor2(core.Qt__blue), core.Qt__SolidPattern))
s.mergeFormatOnLineOrSelection(cfmt)
}
s.editor.Document().SetModified(true)
}
}
//return url or ""
func (s *myWindow) getSelectedImage() (url string) {
cursor := s.editor.TextCursor()
if cursor == nil {
return ""
}
fragment := cursor.Selection()
if fragment.IsEmpty() {
return ""
}
html := fragment.ToHtml(core.NewQByteArray2("UTF-8", 5))
reg1, err := regexp.Compile(`<!--StartFragment-->.+<!--EndFragment-->`)
if err != nil {
log.Println(err)
return ""
}
html = reg1.FindString(html)
reg2, err := regexp.Compile(`<img src="([^"]+)" />`)
if err != nil {
log.Println(err)
return ""
}
urls := reg2.FindAllStringSubmatch(html, -1)
if len(urls) != 1 {
return ""
}
return urls[0][1]
}
func (s *myWindow) clearModel() {
s.model.Clear()
s.model.SetHorizontalHeaderLabels([]string{T("Diary List") + " - " + s.categoryName})
}
func (s *myWindow) clearModelFind() {
s.modelFind.Clear()
s.modelFind.SetHorizontalHeaderLabels([]string{T("Result List") + " - " + s.categoryName})
}
func (s *myWindow) lastUser() string {
v, err := ioutil.ReadFile(path.Join(datDir, "user.txt"))
if err != nil {
return ""
}
return string(v)
}
func (s *myWindow) saveLastUser(name string) {
path1 := path.Join(datDir, "user.txt")
ioutil.WriteFile(path1, []byte(name), 0644)
}
func (s *myWindow) mergeFormatOnLineOrSelection(format *gui.QTextCharFormat) *gui.QTextCursor {
var cursor = s.editor.TextCursor()
if !cursor.HasSelection() {
cursor.Select(gui.QTextCursor__LineUnderCursor)
}
cursor.MergeCharFormat(format)
s.editor.MergeCurrentCharFormat(format)
return cursor
}
func (s *myWindow) rename() {
dlg := widgets.NewQDialog(s.window, core.Qt__Dialog)
dlg.SetWindowTitle(T("Rename"))
grid := newGridLayout(dlg)
name := widgets.NewQLabel2(T("New Name:"), dlg, core.Qt__Widget)
grid.AddWidget2(name, 0, 0, 0)
nameInput := widgets.NewQLineEdit(dlg)
grid.AddWidget2(nameInput, 0, 1, 0)
okAct := widgets.NewQPushButton2(T("OK"), dlg)
grid.AddWidget2(okAct, 1, 0, 0)
cancelAct := widgets.NewQPushButton2(T("Cancel"), dlg)
grid.AddWidget2(cancelAct, 1, 1, 0)
okAct.ConnectClicked(func(checked bool) {
ret := widgets.QMessageBox_Question(dlg, T("Confirm"), T("Are you sure?"), widgets.QMessageBox__Yes|widgets.QMessageBox__Cancel, widgets.QMessageBox__Yes)
//fmt.Println(ret)
if ret == widgets.QMessageBox__Yes {
if len(nameInput.Text()) == 0 {
return
}
s.db.Close()
dstName := path.Join(path.Dir(dataDir), nameInput.Text())
err := os.Rename(dataDir, dstName)
if err == nil {
widgets.QMessageBox_Information(dlg, T("Information"), T("Success,Please login again."), widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
} else {
widgets.QMessageBox_Information(dlg, T("Information"), T("Fail,Please login again."), widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
}
}
dlg.Hide()
s.window.Close()
})
cancelAct.ConnectClicked(func(c bool) {
dlg.Hide()
dlg.Destroy(true, true)
})
dlg.SetLayout(grid)
dlg.SetModal(true)
dlg.Show()
}
func (s *myWindow) updatePwd() {
dlg := widgets.NewQDialog(s.window, core.Qt__Dialog)
dlg.SetWindowTitle(T("Modify Password"))
grid := newGridLayout(dlg)
pwd1 := widgets.NewQLabel2(T("Old Password:"), dlg, core.Qt__Widget)
grid.AddWidget2(pwd1, 0, 0, 0)
pwdInput1 := widgets.NewQLineEdit(dlg)
pwdInput1.SetEchoMode(widgets.QLineEdit__Password)
pwdInput1.SetPlaceholderText(T("Length Must >= 4"))
grid.AddWidget2(pwdInput1, 0, 1, 0)
pwd2 := widgets.NewQLabel2(T("New Password:"), dlg, core.Qt__Widget)
grid.AddWidget2(pwd2, 1, 0, 0)
pwdInput2 := widgets.NewQLineEdit(dlg)
pwdInput2.SetEchoMode(widgets.QLineEdit__Password)
pwdInput2.SetPlaceholderText(T("Length Must >= 4"))
grid.AddWidget2(pwdInput2, 1, 1, 0)
pwd3 := widgets.NewQLabel2(T("Confirm Password:"), dlg, core.Qt__Widget)
grid.AddWidget2(pwd3, 2, 0, 0)
pwdInput3 := widgets.NewQLineEdit(dlg)
pwdInput3.SetEchoMode(widgets.QLineEdit__Password)
pwdInput3.SetPlaceholderText(T("Length Must >= 4"))
grid.AddWidget2(pwdInput3, 2, 1, 0)
okAct := widgets.NewQPushButton2(T("OK"), dlg)
grid.AddWidget2(okAct, 3, 0, 0)
cancelAct := widgets.NewQPushButton2(T("Cancel"), dlg)
grid.AddWidget2(cancelAct, 3, 1, 0)
okAct.ConnectClicked(func(checked bool) {
ret := widgets.QMessageBox_Question(dlg, T("Confirm"), T("Are you sure?"), widgets.QMessageBox__Yes|widgets.QMessageBox__Cancel, widgets.QMessageBox__Yes)
if ret == widgets.QMessageBox__Yes {
if len(pwdInput3.Text()) < 4 {
return
}
if pwdInput2.Text() != pwdInput3.Text() {
return
}
err := s.db.UpdateRealKeyAndSha40(pwdInput1.Text(), pwdInput2.Text())
if err == nil {
widgets.QMessageBox_Information(dlg, T("Information"), T("Success,Please login again."), widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
dlg.Hide()
s.window.Close()
} else {
widgets.QMessageBox_Information(dlg, T("Information"), T("Fail")+err.Error(), widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
}
}
dlg.Hide()
dlg.Destroy(true, true)
})
cancelAct.ConnectClicked(func(c bool) {
dlg.Hide()
dlg.Destroy(true, true)
})
dlg.SetLayout(grid)
dlg.SetModal(true)
dlg.Show()
}
func (s *myWindow) getUsers() []string {
dir := datDir
hdir, err := os.Open(dir)
if err != nil {
return []string{}
}
dirs, err := hdir.Readdir(-1)
if err != nil {
return nil
}
res := []string{}
for _, v := range dirs {
if v.IsDir() {
res = append(res, v.Name())
}
}
return res
}
func (s *myWindow) login() {
dlg := widgets.NewQDialog(s.window, core.Qt__Dialog)
dlg.SetWindowTitle(T("Login"))
grid := newGridLayout(dlg)
name := widgets.NewQLabel2(T("Name:"), dlg, core.Qt__Widget)
grid.AddWidget2(name, 0, 0, 0)
nameInput := widgets.NewQComboBox(dlg)
nameInput.SetEditable(true)
nameInput.AddItems(s.getUsers())
nameInput.SetCurrentText(s.lastUser())
grid.AddWidget2(nameInput, 0, 1, 0)
pwd := widgets.NewQLabel2(T("Password:"), dlg, core.Qt__Widget)
grid.AddWidget2(pwd, 1, 0, 0)
pwdInput := widgets.NewQLineEdit(dlg)
pwdInput.SetEchoMode(widgets.QLineEdit__Password)
pwdInput.SetPlaceholderText(T("Length Must >= 4"))
if len(nameInput.CurrentText()) > 0 {
pwdInput.SetFocus2()
}
grid.AddWidget2(pwdInput, 1, 1, 0)
btb := newGridLayout2()
okBtn := widgets.NewQPushButton2(T("OK"), dlg)
btb.AddWidget2(okBtn, 0, 0, 0)
regBtn := widgets.NewQPushButton2(T("Register"), dlg)
regBtn.SetToolTip(T("Please input the name and password to register before you click this button!"))
btb.AddWidget2(regBtn, 0, 1, 0)
cancelBtn := widgets.NewQPushButton2(T("Cancel"), dlg)
btb.AddWidget2(cancelBtn, 0, 2, 0)
grid.AddLayout2(btb, 2, 0, 1, 2, 0)
dlg.SetLayout(grid)
dlg.SetModal(true)
minLen := 4
okBtn.ConnectClicked(func(b bool) {
var err error
if len(pwdInput.Text()) < minLen || len(nameInput.CurrentText()) < 1 {
return
}
s.db, err = getMyDb(nameInput.CurrentText())
if err != nil {
widgets.QMessageBox_Information(dlg, T("Information"), T("Fail"), widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
nameInput.SetFocus2()
return
}
s.key, err = s.db.GetRealKey(pwdInput.Text())
if err != nil {
widgets.QMessageBox_Information(dlg, T("Information"), T("Fail"), widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
pwdInput.SetFocus2()
return
}
s.saveLastUser(nameInput.CurrentText())
s.user = nameInput.CurrentText()
s.window.SetWindowTitle(nameInput.CurrentText())
dlg.Hide()
})
regBtn.ConnectClicked(func(b bool) {
if len(pwdInput.Text()) < minLen || len(nameInput.CurrentText()) < 1 {
widgets.QMessageBox_Warning(s.window, T("Register"),
T("Please input the name and password to register before you click this button!"), widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
return
}
var ok bool
confirm := widgets.QInputDialog_GetText(dlg, T("Confirm"), T("Name:")+nameInput.CurrentText(), widgets.QLineEdit__Password, "",
&ok, core.Qt__Dialog, core.Qt__ImhNone)
if !ok {
return
}
if confirm != pwdInput.Text() {
s.showMsg(T("Fail"), T("Password Not Match"))
return
}
err := createUserDb(nameInput.CurrentText(), pwdInput.Text())
if err != nil {
panic(err)
}
s.db, err = getMyDb(nameInput.CurrentText())
if err != nil {
panic(err)
}
s.key, err = s.db.GetRealKey(pwdInput.Text())
if err != nil {
panic(err)
}
s.saveLastUser(nameInput.CurrentText())
s.user = nameInput.CurrentText()
s.window.SetWindowTitle(nameInput.CurrentText())
dlg.Hide()
})
cancelBtn.ConnectClicked(func(b bool) {
dlg.Destroy(true, true)
s.window.Destroy(true, true)
s.app.Quit()
})
dlg.ConnectCloseEvent(func(e *gui.QCloseEvent) {
dlg.Destroy(true, true)
s.window.Destroy(true, true)
s.app.Quit()
})
dlg.ConnectHideEvent(func(e *gui.QHideEvent) {
//log.Println("load list")
s.loadUserCategorys()
dlg.Destroy(true, true)
})
dlg.Show()
dlg.Move2(0, 0)
dlg.Move2(s.window.X()+(s.window.Width()-dlg.Width())/2, s.window.Y()+(s.window.Height()-dlg.Width())/2)
}
func (s *myWindow) exportEncryptedDiary() {
//export private format .egf (encrypted gob file)
idx := s.tree.CurrentIndex()
if idx == nil {
return
}
item := s.model.ItemFromIndex(idx)
if item == nil {
return
}
dlg := widgets.NewQDialog(s.window, core.Qt__Dialog)
dlg.SetWindowTitle(T("Export Encrypted Diary") + "...")
grid := newGridLayout2()
name := widgets.NewQLabel2(T("FileName:"), dlg, core.Qt__Widget)
grid.AddWidget2(name, 0, 0, 0)
nameInput := widgets.NewQLineEdit(dlg)
grid.AddWidget2(nameInput, 0, 1, 0)
nameInput.SetPlaceholderText(T("Double click to select..."))
nameInput.SetMinimumWidth(240)
passwd := widgets.NewQLabel2(T("Password:"), dlg, core.Qt__Widget)
grid.AddWidget2(passwd, 1, 0, 0)
passwdInput := widgets.NewQLineEdit(dlg)
grid.AddWidget2(passwdInput, 1, 1, 0)
passwdInput.SetEchoMode(widgets.QLineEdit__Password)
passwdInput.SetPlaceholderText(T("Length Must >= 4"))
hbox := widgets.NewQHBoxLayout()
okBtn := widgets.NewQPushButton2(T("OK"), dlg)
hbox.AddWidget(okBtn, 1, 0)
cancelBtn := widgets.NewQPushButton2(T("Cancel"), dlg)
hbox.AddWidget(cancelBtn, 1, 0)
cancelBtn.ConnectClicked(func(b bool) {
dlg.Hide()
dlg.Destroy(true, true)
})
nameInput.ConnectMouseDoubleClickEvent(func(e *gui.QMouseEvent) {
filename := widgets.QFileDialog_GetSaveFileName(dlg, T("Export To..."), ".", "Encrypted Diary (*.egf)", "Encrypted Diary (*.egf)", 0)
if strings.HasSuffix(strings.ToLower(filename), ".egf") {
nameInput.SetText(filename)
} else {
nameInput.SetText(filename + ".egf")
}
})
okBtn.ConnectClicked(func(b bool) {
if len(passwdInput.Text()) < 4 {
return
}
filename := strings.TrimSpace(nameInput.Text())
if len(filename) == 0 {
return
}
key := getSha4(passwdInput.Text())
data := s.getRichText()
err := encodeToPathName(data, filename, key)
if err != nil {
s.showMsg(T("Error"), err.Error())
} else {
s.showMsg(T("Success"), filename)
}
dlg.Hide()
dlg.Destroy(true, true)
})
grid.AddLayout2(hbox, 2, 0, 1, 2, 0)
dlg.SetLayout(grid)
dlg.Exec()
}
func (s *myWindow) importEncryptedDiary() {
//import private format .egf (encrypted gob file)
dlg := widgets.NewQDialog(s.window, core.Qt__Dialog)
dlg.SetWindowTitle(T("Import Encrypted Diary") + "...")
grid := newGridLayout2()
name := widgets.NewQLabel2(T("FileName:"), dlg, core.Qt__Widget)
grid.AddWidget2(name, 0, 0, 0)
nameInput := widgets.NewQLineEdit(dlg)
grid.AddWidget2(nameInput, 0, 1, 0)
nameInput.SetPlaceholderText(T("Double click to select..."))
nameInput.SetMinimumWidth(240)
passwd := widgets.NewQLabel2(T("Password:"), dlg, core.Qt__Widget)
grid.AddWidget2(passwd, 1, 0, 0)
passwdInput := widgets.NewQLineEdit(dlg)
grid.AddWidget2(passwdInput, 1, 1, 0)
passwdInput.SetEchoMode(widgets.QLineEdit__Password)
hbox := widgets.NewQHBoxLayout()
okBtn := widgets.NewQPushButton2(T("OK"), dlg)
hbox.AddWidget(okBtn, 1, 0)
cancelBtn := widgets.NewQPushButton2(T("Cancel"), dlg)
hbox.AddWidget(cancelBtn, 1, 0)
cancelBtn.ConnectClicked(func(b bool) {
dlg.Hide()
dlg.Destroy(true, true)
})
nameInput.ConnectMouseDoubleClickEvent(func(e *gui.QMouseEvent) {
filename := widgets.QFileDialog_GetOpenFileName(dlg, T("Import File..."), ".", "Encrypted Diary .egf (*.egf)", "Encrypted Diary .egf (*.egf)", widgets.QFileDialog__ReadOnly)
nameInput.SetText(filename)
})
okBtn.ConnectClicked(func(b bool) {
if len(passwdInput.Text()) < 4 {
return
}
filename := strings.TrimSpace(nameInput.Text())
if len(filename) == 0 {
return
}
key := getSha4(passwdInput.Text())
data, err := decodeFromPathName(filename, key)
if err != nil {
return
}
now := time.Now()
s.addDiary(now.Format("2006-01"), now.Format("02"), "")
_, err = s.getQText(data)
if err == nil {
s.editor.SetHtml(s.document.Html)
s.showAttachList()
//curDiary.Modified = true
s.editor.Document().SetModified(true)
s.saveCurDiary()
} else {
s.showMsg(T("Error"), err.Error())
}
dlg.Hide()
dlg.Destroy(true, true)
})
grid.AddLayout2(hbox, 2, 0, 1, 2, 0)
dlg.SetLayout(grid)
dlg.Exec()
}
func (s *myWindow) exportAsPdf() {
defaultName := strings.TrimSpace(s.editor.Document().FirstBlock().Text()) + ".pdf"
filename := widgets.QFileDialog_GetSaveFileName(s.window, T("Export To..."), defaultName, "PDF (*.pdf)", "Encrypted Diary (*.pdf)", 0)
if !strings.HasSuffix(strings.ToLower(filename), ".pdf") {
filename = filename + ".pdf"
}
var (
fileName = filename
printer = printsupport.NewQPrinter(printsupport.QPrinter__HighResolution)
)
printer.SetOutputFormat(printsupport.QPrinter__PdfFormat)
printer.SetOutputFileName(fileName)
s.editor.Document().Print(printer)
s.setStatusBar(fmt.Sprintf("Exported %v", core.QDir_ToNativeSeparators(fileName)))
}
func (s *myWindow) exportAsOdt() {
defaultName := strings.TrimSpace(s.editor.Document().FirstBlock().Text()) + ".odt"
filename := widgets.QFileDialog_GetSaveFileName(s.window, T("Export To..."), defaultName, "OpenDocument (*.odt)", "OpenDocument (*.odt)", 0)
if !strings.HasSuffix(strings.ToLower(filename), ".odt") {
filename = filename + ".odt"
}
var (
writer = gui.NewQTextDocumentWriter3(filename, core.NewQByteArray())
success = writer.Write(s.editor.Document())
)
if success {
s.setStatusBar(fmt.Sprintf("Exported %v", core.QDir_ToNativeSeparators(filename)))
} else {
s.setStatusBar("Exported Fail.")
}
}
func (s *myWindow) showMsg(title, msg string) {
dlg := widgets.NewQMessageBox(s.window)
dlg.SetWindowTitle(title)
dlg.SetText(msg)
dlg.Exec()
dlg.Destroy(true, true)
}
func (s *myWindow) showPay() {
dlg := widgets.NewQDialog(s.window, core.Qt__Dialog)
dlg.SetWindowTitle(T("Pay Voluntary!"))
box := widgets.NewQHBoxLayout2(dlg)
height := 512
labelAli := widgets.NewQLabel(dlg, core.Qt__Widget)
img1 := newQPixMap(":/qml/pay/alipay.png", "png", core.Qt__NoFormatConversion)
img1 = img1.ScaledToHeight(height, core.Qt__SmoothTransformation)
labelAli.SetPixmap(img1)
box.AddWidget(labelAli, 1, 0)
labelWx := widgets.NewQLabel(dlg, core.Qt__Widget)
img2 := newQPixMap(":/qml/pay/wxpay.png", "png", core.Qt__NoFormatConversion)
img2 = img2.ScaledToHeight(height, core.Qt__SmoothTransformation)
labelWx.SetPixmap(img2)
box.AddWidget(labelWx, 1, 0)
dlg.SetLayout(box)
dlg.Exec()
dlg.Destroy(true, true)
}
func main() {
//defer gettext.SaveLog()
app := widgets.NewQApplication(len(os.Args), os.Args)
window := new(myWindow)
window.Create(app)
app.Exec()
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化