You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1128 lines
27 KiB

package app
import (
"errors"
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
"log"
"os"
"path"
"path/filepath"
"regexp"
"strings"
"videosrt/app/aliyun"
"videosrt/app/tool"
"videosrt/app/translate"
)
type MyMainWindow struct {
*walk.MainWindow
}
//创建一个提示消息
func (mw *MyMainWindow) NewInformationTips(title string , message string) {
walk.MsgBox(mw, title , message , walk.MsgBoxIconInformation)
}
//创建一个错误消息
func (mw *MyMainWindow) NewErrormationTips(title string , message string) {
walk.MsgBox(mw, title , message , walk.MsgBoxIconWarning)
}
// 运行 应用设置 Dialog
func(mw *MyMainWindow) RunAppSetingDialog(owner walk.Form , confirmCall func(*AppSetings)) {
var seting *AppSetings
var dlg *walk.Dialog
var db *walk.DataBinder
var acceptPB, cancelPB *walk.PushButton
seting = Setings.GetCacheAppSetingsData() //查询缓存数据
//fmt.Println( setings )
if seting.MaxConcurrency == 0 {
seting.MaxConcurrency = 2 //默认并发数
}
Dialog{
AssignTo: &dlg,
Title: "软件设置",
Font:Font{Family: "微软雅黑", PointSize: 9},
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
DataBinder: DataBinder{
AssignTo: &db,
Name: "setings",
DataSource: seting,
ErrorPresenter: ToolTipErrorPresenter{},
},
MinSize: Size{450, 220},
Layout: VBox{},
Children: []Widget{
Composite{
Layout: Grid{Columns: 2},
Children: []Widget{
Label{
Text: "任务处理并发数:",
},
NumberEdit{
Value: Bind("MaxConcurrency", Range{1, 20}),
Decimals: 0,
},
Label{
Text: "文件输出目录:",
},
LineEdit{
Text: Bind("SrtFileDir"),
},
Label{
ColumnSpan: 2,
Text: "说明:\r\n“文件输出目录” 若留空,则默认与媒体文件输出到同一目录下",
TextColor:walk.RGB(190 , 190 , 190),
MinSize:Size{Height:40},
},
Label{
Text: "关闭软件智能分段处理:",
},
CheckBox{
Checked: Bind("CloseIntelligentBlockSwitch"),
},
Label{
Text: "关闭OSS临时文件清理:",
},
CheckBox{
Checked: Bind("CloseAutoDeleteOssTempFile"),
},
Label{
Text: "关闭软件新版本提醒:",
},
CheckBox{
Checked: Bind("CloseNewVersionMessage"),
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
HSpacer{},
PushButton{
AssignTo: &acceptPB,
Text: "保存",
OnClicked: func() {
if err := db.Submit(); err != nil {
log.Fatal(err)
return
}
//目录校验
if seting.SrtFileDir != "" {
tmpDir := tool.WinDir(seting.SrtFileDir)
if !tool.DirExists(tmpDir) {
mw.NewErrormationTips("错误" , "目录无效/不存在:" + seting.SrtFileDir)
return;
}
seting.SrtFileDir = tmpDir
}
//设置缓存
Setings.SetCacheAppSetingsData(seting)
//设置回调
confirmCall(seting)
dlg.Accept()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "取消",
OnClicked: func() { dlg.Cancel() },
},
},
},
},
}.Run( owner )
}
// 运行 新建语音引擎 Dialog
func(mw *MyMainWindow) RunSpeechEngineSetingDialog(owner walk.Form , confirmCall func()) {
var engine *AliyunEngineCache
var dlg *walk.Dialog
var db *walk.DataBinder
var acceptPB, cancelPB *walk.PushButton
engine = new(AliyunEngineCache)
engine.Region = aliyun.ALIYUN_CLOUND_REGION_CHA //默认值
Dialog{
AssignTo: &dlg,
Title: "新建语音引擎",
Font:Font{Family: "微软雅黑", PointSize: 9},
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
DataBinder: DataBinder{
AssignTo: &db,
Name: "engine",
DataSource: engine,
ErrorPresenter: ToolTipErrorPresenter{},
},
MinSize: Size{500, 300},
Layout: VBox{},
Children: []Widget{
Composite{
Layout: Grid{Columns: 2},
Children: []Widget{
Label{
Text: "名称/别名:",
},
LineEdit{
Text: Bind("Alias"),
},
Label{
Text: "AppKey:",
},
LineEdit{
Text: Bind("AppKey"),
},
Label{
Text: "AccessKeyId:",
},
LineEdit{
Text: Bind("AccessKeyId"),
},
Label{
Text: "AccessKeySecret:",
},
LineEdit{
Text: Bind("AccessKeySecret"),
},
Label{
Text: "服务区域:",
},
ComboBox{
Value: Bind("Region", SelRequired{}),
BindingMember: "Id",
DisplayMember: "Name",
Model: GetAliyunEngineRegionOptionSelects(),
},
Label{
ColumnSpan: 2,
Text: "说明:\r\n“语音识别” 目前使用的是阿里云语音服务商,请填写相关的引擎配置。",
TextColor:walk.RGB(190 , 190 , 190),
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
HSpacer{},
PushButton{
AssignTo: &acceptPB,
Text: "确定新增",
OnClicked: func() {
if err := db.Submit(); err != nil {
log.Print(err)
return
}
//参数验证
if (engine.Alias == "") {
mw.NewErrormationTips("提示" , "请填写 名称/别名")
return
}
if (engine.AppKey == "") {
mw.NewErrormationTips("提示" , "请填写 AppKey")
return
}
if (engine.AccessKeyId == "") {
mw.NewErrormationTips("提示" , "请填写 AccessKeyId")
return
}
if (engine.AccessKeySecret == "") {
mw.NewErrormationTips("提示" , "请填写 AccessKeySecret")
return
}
//去空格
engine.AppKey = strings.TrimSpace(engine.AppKey)
engine.AccessKeyId = strings.TrimSpace(engine.AccessKeyId)
engine.AccessKeySecret = strings.TrimSpace(engine.AccessKeySecret)
//获取缓存数据
localData := Engine.GetCacheAliyunEngineListData()
//生成id
lens := len(localData.Engine)
if lens == 0 {
engine.Id = 1
} else {
engine.Id = localData.Engine[ lens - 1 ].Id + 1
}
//追加数据
localData.Engine = append(localData.Engine , engine)
//缓存数据
Engine.SetCacheAliyunEngineListData(localData)
//调用回调
confirmCall()
dlg.Accept()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "取消",
OnClicked: func() { dlg.Cancel() },
},
},
},
},
}.Run( owner )
}
// 运行 新建[百度]翻译引擎 Dialog
func(mw *MyMainWindow) RunBaiduTranslateEngineSetingDialog(owner walk.Form , confirmCall func()) {
var engine *TranslateEngineStruct
var dlg *walk.Dialog
var db *walk.DataBinder
var acceptPB, cancelPB *walk.PushButton
engine = new(TranslateEngineStruct)
//默认值
engine.Supplier = TRANSLATE_SUPPLIER_BAIDU
engine.BaiduEngine.AuthenType = translate.ACCOUNT_COMMON_AUTHEN
Dialog{
AssignTo: &dlg,
Title: "新建翻译引擎(百度翻译)",
Font:Font{Family: "微软雅黑", PointSize: 9},
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
DataBinder: DataBinder{
AssignTo: &db,
Name: "engine",
DataSource: engine,
ErrorPresenter: ToolTipErrorPresenter{},
},
MinSize: Size{500, 300},
Layout: VBox{},
Children: []Widget{
Composite{
Layout: Grid{Columns: 2},
Children: []Widget{
Label{
Text: "名称/别名:",
},
LineEdit{
Text: Bind("Alias"),
},
Label{
Text: "AppId:",
},
LineEdit{
Text: Bind("BaiduEngine.AppId"),
},
Label{
Text: "AppSecret:",
},
LineEdit{
Text: Bind("BaiduEngine.AppSecret"),
},
Label{
Text: "账号认证类型:",
},
ComboBox{
Value: Bind("BaiduEngine.AuthenType", SelRequired{}),
BindingMember: "Id",
DisplayMember: "Name",
Model: GetBaiduTranslateAuthenTypeOptionsSelects(),
},
TextLabel{
ColumnSpan: 2,
Row: 5,
Text: "\r\n说明:\r\n请填写在 “百度翻译开放平台” 的申请密钥,注意 “标准版” 和 “高级版” 的选择",
TextColor:walk.RGB(190 , 190 , 190),
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
HSpacer{},
PushButton{
AssignTo: &acceptPB,
Text: "确定新增",
OnClicked: func() {
if err := db.Submit(); err != nil {
log.Print(err)
return
}
//参数验证
if (engine.Alias == "") {
mw.NewErrormationTips("提示" , "请填写 名称/别名")
return
}
if (engine.BaiduEngine.AppId == "") {
mw.NewErrormationTips("提示" , "请填写 AppId")
return
}
if (engine.BaiduEngine.AppSecret == "") {
mw.NewErrormationTips("提示" , "请填写 AppSecret")
return
}
//去空格
engine.BaiduEngine.AppId = strings.TrimSpace(engine.BaiduEngine.AppId)
engine.BaiduEngine.AppSecret = strings.TrimSpace(engine.BaiduEngine.AppSecret)
//获取缓存数据
localData := Translate.GetCacheTranslateEngineListData()
//生成id
lens := len(localData.Engine)
if lens == 0 {
engine.Id = 1
} else {
engine.Id = localData.Engine[ lens - 1 ].Id + 1
}
//追加数据
localData.Engine = append(localData.Engine , engine)
//缓存数据
Translate.SetCacheTranslateEngineListData(localData)
//调用回调
confirmCall()
dlg.Accept()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "取消",
OnClicked: func() { dlg.Cancel() },
},
},
},
},
}.Run( owner )
}
// 运行 新建[腾讯云]翻译引擎 Dialog
func(mw *MyMainWindow) RunTengxunyunTranslateEngineSetingDialog(owner walk.Form , confirmCall func()) {
var engine *TranslateEngineStruct
var dlg *walk.Dialog
var db *walk.DataBinder
var acceptPB, cancelPB *walk.PushButton
engine = new(TranslateEngineStruct)
//默认值
engine.Supplier = TRANSLATE_SUPPLIER_TENGXUNYUN
Dialog{
AssignTo: &dlg,
Title: "新建翻译引擎(腾讯云)",
Font:Font{Family: "微软雅黑", PointSize: 9},
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
DataBinder: DataBinder{
AssignTo: &db,
Name: "engine",
DataSource: engine,
ErrorPresenter: ToolTipErrorPresenter{},
},
MinSize: Size{500, 300},
Layout: VBox{},
Children: []Widget{
Composite{
Layout: Grid{Columns: 2},
Children: []Widget{
Label{
Text: "名称/别名:",
},
LineEdit{
Text: Bind("Alias"),
},
Label{
Text: "SecretId:",
},
LineEdit{
Text: Bind("TengxunyunEngine.SecretId"),
},
Label{
Text: "SecretKey:",
},
LineEdit{
Text: Bind("TengxunyunEngine.SecretKey"),
},
TextLabel{
ColumnSpan: 2,
Row: 5,
Text: "\r\n说明:\r\n请填写 “腾讯云” 创建的子用户密钥",
TextColor:walk.RGB(190 , 190 , 190),
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
HSpacer{},
PushButton{
AssignTo: &acceptPB,
Text: "确定新增",
OnClicked: func() {
if err := db.Submit(); err != nil {
log.Print(err)
return
}
//参数验证
if (engine.Alias == "") {
mw.NewErrormationTips("提示" , "请填写 名称/别名")
return
}
if (engine.TengxunyunEngine.SecretId == "") {
mw.NewErrormationTips("提示" , "请填写 SecretId")
return
}
if (engine.TengxunyunEngine.SecretKey == "") {
mw.NewErrormationTips("提示" , "请填写 SecretKey")
return
}
//去空格
engine.TengxunyunEngine.SecretId = strings.TrimSpace(engine.TengxunyunEngine.SecretId)
engine.TengxunyunEngine.SecretKey = strings.TrimSpace(engine.TengxunyunEngine.SecretKey)
//获取缓存数据
localData := Translate.GetCacheTranslateEngineListData()
//生成id
lens := len(localData.Engine)
if lens == 0 {
engine.Id = 1
} else {
engine.Id = localData.Engine[ lens - 1 ].Id + 1
}
//追加数据
localData.Engine = append(localData.Engine , engine)
//缓存数据
Translate.SetCacheTranslateEngineListData(localData)
//调用回调
confirmCall()
dlg.Accept()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "取消",
OnClicked: func() { dlg.Cancel() },
},
},
},
},
}.Run( owner )
}
//运行 Oss对象存储配置 Dialog
func (mw *MyMainWindow) RunObjectStorageSetingDialog(owner walk.Form) {
var oss *AliyunOssCache
var dlg *walk.Dialog
var db *walk.DataBinder
var acceptPB, cancelPB *walk.PushButton
oss = Oss.GetCacheAliyunOssData() //查询缓存数据
Dialog{
AssignTo: &dlg,
Title: "OSS对象存储设置",
Font:Font{Family: "微软雅黑", PointSize: 9},
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
DataBinder: DataBinder{
AssignTo: &db,
Name: "oss",
DataSource: oss,
ErrorPresenter: ToolTipErrorPresenter{},
},
MinSize: Size{500, 300},
Layout: VBox{},
Children: []Widget{
Composite{
Layout: Grid{Columns: 2},
Children: []Widget{
Label{
Text: "Endpoint:",
},
LineEdit{
Text: Bind("Endpoint"),
},
Label{
Text: "AccessKeyId:",
},
LineEdit{
Text: Bind("AccessKeyId"),
},
Label{
Text: "AccessKeySecret:",
},
LineEdit{
Text: Bind("AccessKeySecret"),
},
Label{
Text: "BucketName:",
},
LineEdit{
Text: Bind("BucketName"),
},
Label{
Text: "BucketDomain:",
},
LineEdit{
Text: Bind("BucketDomain"),
},
Label{
ColumnSpan: 2,
Text: "说明:\r\n“OSS对象存储”目前使用的是阿里云服务,请填写相关的服务配置。",
TextColor:walk.RGB(190 , 190 , 190),
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
HSpacer{},
PushButton{
AssignTo: &acceptPB,
Text: "保存",
OnClicked: func() {
if err := db.Submit(); err != nil {
log.Fatal(err)
return
}
//参数验证
if (oss.Endpoint == "") {
mw.NewInformationTips("提示" , "请填写 Endpoint")
return
}
if (oss.AccessKeyId == "") {
mw.NewInformationTips("提示" , "请填写 AccessKeyId")
return
}
if (oss.AccessKeySecret == "") {
mw.NewInformationTips("提示" , "请填写 AccessKeySecret")
return
}
if (oss.BucketName == "") {
mw.NewInformationTips("提示" , "请填写 BucketName")
return
}
if (oss.BucketDomain == "") {
mw.NewInformationTips("提示" , "请填写 BucketDomain")
return
}
//去空格
oss.Endpoint = strings.TrimSpace(oss.Endpoint)
oss.AccessKeyId = strings.TrimSpace(oss.AccessKeyId)
oss.AccessKeySecret = strings.TrimSpace(oss.AccessKeySecret)
oss.BucketName = strings.TrimSpace(oss.BucketName)
oss.BucketDomain = strings.TrimSpace(oss.BucketDomain)
//设置缓存
Oss.SetCacheAliyunOssData(oss)
dlg.Accept()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "取消",
OnClicked: func() { dlg.Cancel() },
},
},
},
},
}.Run( owner )
}
//运行 语气词过滤设置 Dialog
func (mw *MyMainWindow) RunGlobalFilterSetingDialog (owner walk.Form , historyWords string , confirmCall func(words string)) {
var dlg *walk.Dialog
var db *walk.DataBinder
var acceptPB, cancelPB *walk.PushButton
var tmpData = new(AppFilterSetings)
tmpData.GlobalFilter.Words = historyWords
Dialog{
AssignTo: &dlg,
Title: "全局语气词过滤设置",
Font:Font{Family: "微软雅黑", PointSize: 9},
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
DataBinder: DataBinder{
AssignTo: &db,
Name: "filter",
DataSource: tmpData,
},
MinSize: Size{500, 300},
Layout: VBox{},
Children: []Widget{
Composite{
Layout: Grid{Columns: 2},
Children: []Widget{
Label{
ColumnSpan: 1,
Text: "过滤语气词:",
},
TextEdit{
ColumnSpan: 1,
MinSize: Size{150, 80},
Text: Bind("GlobalFilter.Words"),
VScroll: true,
},
Label{
ColumnSpan: 2,
Text: "说明:\r\n“过滤语气词” 支持设置多个,请保持每个词语都单独一行",
TextColor:walk.RGB(190 , 190 , 190),
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
HSpacer{},
PushButton{
AssignTo: &acceptPB,
Text: "保存",
OnClicked: func() {
if err := db.Submit(); err != nil {
log.Fatal(err)
return
}
confirmCall(tmpData.GlobalFilter.Words)
//参数验证
dlg.Accept()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "取消",
OnClicked: func() { dlg.Cancel() },
},
},
},
},
}.Run( owner )
}
type DefinedRuleTableRows struct {
Id int
Target string //目标规则
Replace string //替换规则
Way int //规则类型
}
type DefinedRuleTableModel struct {
walk.SortedReflectTableModelBase
maxIndex int
items []*DefinedRuleTableRows
}
func NewDefinedRuleTableModel () *DefinedRuleTableModel {
t := new(DefinedRuleTableModel)
return t
}
func (m *DefinedRuleTableModel) Items() interface{} {
return m.items
}
func (m *DefinedRuleTableModel) AddRow (row *DefinedRuleTableRows) {
m.maxIndex++
row.Id = m.maxIndex;
m.items = append(m.items , row)
}
func (m *DefinedRuleTableModel) BatchDelRow (indexs []int) {
id := make([]int , 0)
for row_i , row_v := range m.items {
for _ , op_v := range indexs {
if row_i == op_v {
id = append(id , row_v.Id)
}
}
}
for _ , vid := range id {
m.DelRow(vid)
}
}
func (m *DefinedRuleTableModel) GetRowIndex (index int) *DefinedRuleTableRows {
tmp := new(DefinedRuleTableRows)
for row_i , row_v := range m.items {
if row_i == index {
tmp = row_v
break
}
}
return tmp
}
func (m *DefinedRuleTableModel) DelRow (id int) {
t := len(m.items)
for row_i , row_v := range m.items {
if row_v.Id == id {
if row_i == 0 {
if t <= 1 {
m.items = make([]*DefinedRuleTableRows , 0)
} else {
m.items = m.items[row_i+1:]
}
} else if row_i+1 >= t {
m.items = m.items[:row_i]
} else {
m.items = append(m.items[:row_i] , m.items[row_i+1:]...)
}
break
}
}
}
func (tv *DefinedRuleTableModel) SetAndInitFilterRules (rules []*AppDefinedFilterRule) {
//初始化
tv.maxIndex = 0
tv.items = make([]*DefinedRuleTableRows , 0)
for _ , v := range rules {
tv.maxIndex++
tv.items = append(tv.items , &DefinedRuleTableRows{
Id:tv.maxIndex,
Target:v.Target,
Replace:v.Replace,
Way:v.Way,
})
}
}
func (tv *DefinedRuleTableModel) GetFilterRuleResult () []*AppDefinedFilterRule {
result := make([]*AppDefinedFilterRule , 0)
for _ , v := range tv.items {
result = append(result , &AppDefinedFilterRule{
Target:v.Target,
Replace:v.Replace,
Way:v.Way,
})
}
return result
}
//运行 自定义过滤设置 Dialog
func (mw *MyMainWindow) RunDefinedFilterSetingDialog (owner walk.Form , historyRule []*AppDefinedFilterRule , confirmCall func(rule []*AppDefinedFilterRule)) {
var dlg *walk.Dialog
var acceptPB, cancelPB *walk.PushButton
var tv *walk.TableView
tableModel := NewDefinedRuleTableModel()
tableModel.SetAndInitFilterRules(historyRule)
var currentIndexs []int = make([]int , 0) //选择的项
Dialog{
AssignTo: &dlg,
Title: "自定义过滤设置",
Font:Font{Family: "微软雅黑", PointSize: 9},
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
MinSize: Size{600, 500},
Layout: VBox{},
Children: []Widget{
Composite{
Layout: Grid{Columns: 2},
Children: []Widget{
PushButton{
Text: "新增规则",
OnClicked: func() {
copyRow := new(DefinedRuleTableRows)
if len(currentIndexs) == 1 {
copyRow = tableModel.GetRowIndex(currentIndexs[0])
}
mw.RunNewDefinedFilterRuleDialog(mw , copyRow , func(rule *DefinedRuleTableRows) {
tableModel.AddRow(rule)
tv.SetModel(tableModel)
})
},
},
PushButton{
Text: "删除规则",
OnClicked: func() {
if len(currentIndexs) < 1 {
mw.NewErrormationTips("错误" , "请选择操作的对象")
return
}
tableModel.BatchDelRow(currentIndexs)
tv.SetModel(tableModel)
},
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
TableView{
Name:"tableView",
AssignTo: &tv,
AlternatingRowBG: true,
NotSortableByHeaderClick: true,
MultiSelection:true,
Columns: []TableViewColumn{
{Title: "编号", DataMember: "Id" , Width:90},
{Title: "类型", DataMember: "Way", Width:90 , FormatFunc: func(value interface{}) string {
switch v := value.(type) {
case int:
if v == FILTER_TYPE_STRING {
return "文本过滤"
}
if v == FILTER_TYPE_REGX {
return "正则过滤"
}
return ""
default:
return ""
}
}},
{Title: "目标规则", DataMember: "Target", Width:165},
{Title: "替换规则", DataMember: "Replace", Width:185},
},
Model: tableModel,
OnSelectedIndexesChanged: func() {
indexs := tv.SelectedIndexes()
if (len(indexs) > 0) {
currentIndexs = indexs
} else {
currentIndexs = []int{}
}
},
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
HSpacer{},
PushButton{
AssignTo: &acceptPB,
Text: "保存",
OnClicked: func() {
confirmCall(tableModel.GetFilterRuleResult())
//参数验证
dlg.Accept()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "取消",
OnClicked: func() { dlg.Cancel() },
},
},
},
},
}.Run(owner)
}
//新建自定义过滤规则 Dialog
func (mw *MyMainWindow) RunNewDefinedFilterRuleDialog (owner walk.Form , copyRows *DefinedRuleTableRows , confirmCall func(rule *DefinedRuleTableRows)) {
var dlg *walk.Dialog
var db *walk.DataBinder
var acceptPB, cancelPB *walk.PushButton
var tmpData = new(DefinedRuleTableRows)
if copyRows.Id != 0 {
tmpData.Target = copyRows.Target
tmpData.Replace = copyRows.Replace
tmpData.Way = copyRows.Way
} else {
tmpData.Way = 1 //默认
}
Dialog{
AssignTo: &dlg,
Title: "新增自定义过滤规则",
Font:Font{Family: "微软雅黑", PointSize: 9},
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
DataBinder: DataBinder{
AssignTo: &db,
Name: "defined",
DataSource: tmpData,
},
MinSize: Size{500, 300},
Layout: VBox{},
Children: []Widget{
Composite{
Layout: Grid{Columns: 2},
Children: []Widget{
Label{
ColumnSpan: 1,
Text: "目标规则:",
},
LineEdit{
ColumnSpan: 1,
MinSize: Size{Width:150},
Text: Bind("Target"),
},
Label{
ColumnSpan: 1,
Text: "替换规则:",
},
LineEdit{
ColumnSpan: 1,
MinSize: Size{Width:150},
Text: Bind("Replace"),
},
Label{
Text: "过滤类型:",
},
ComboBox{
Value: Bind("Way", SelRequired{}),
BindingMember: "Id",
DisplayMember: "Name",
Model: GetFilterTypeOptionsSelects(),
},
Label{
ColumnSpan: 2,
Text: "说明:\r\n1.“目标规则” 填写查找的文本/正则, “替换规则” 填写替换的文本/正则\r\n2.过滤类型为正则时,“替换规则” 允许使用 $1...$9 进行反向引用",
TextColor:walk.RGB(190 , 190 , 190),
},
},
},
Composite{
Layout: HBox{},
Children: []Widget{
HSpacer{},
PushButton{
AssignTo: &acceptPB,
Text: "保存",
OnClicked: func() {
if err := db.Submit(); err != nil {
log.Fatal(err)
return
}
if strings.TrimSpace(tmpData.Target) == "" {
mw.NewErrormationTips("错误" , "必须填写目标规则噢")
return
}
if tmpData.Way == FILTER_TYPE_REGX {
//正则规则
//校验规则
_, e := regexp.Compile(tmpData.Target)
if e != nil {
mw.NewErrormationTips("错误" , "目标正则规则格式校验不通过,请检查是否正确")
return
}
}
confirmCall(tmpData)
//参数验证
dlg.Accept()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "取消",
OnClicked: func() { dlg.Cancel() },
},
},
},
},
}.Run( owner )
}
//打开 Github
func (mw *MyMainWindow) OpenAboutGithub() {
tool.OpenUrl("https://github.com/wxbool/video-srt-windows")
}
//打开 Gitee
func (mw *MyMainWindow) OpenAboutGitee() {
tool.OpenUrl("https://gitee.com/641453620/video-srt-windows")
}
//支持的文件后缀校验
func VaildateHandleFiles(files [] string , mediaExt bool , srtExt bool) ([]string , error) {
result := []string{}
allowExts := []string{}
mediaExts := []string{
".mp4",".mpeg",".mkv",".wmv",".avi",".m4v",".mov",".flv",".rmvb",".3gp",".f4v",
".mp3",".wav",".aac",".wma",".flac",".m4a",
}
srtExts := []string{".srt"}
if mediaExt {
allowExts = append(allowExts , mediaExts...)
}
if srtExt {
allowExts = append(allowExts , srtExts...)
}
for _,f := range files {
f = tool.WinDir(f)
if thisFile, err := os.Stat(f); err != nil {
if os.IsNotExist(err) {
return result , errors.New("文件不存在:" + f)
}
return result , errors.New("文件校验不通过:" + f)
} else {
if thisFile.IsDir() {
return result , errors.New("不允许操作文件夹:" + f)
}
//校验视频格式后缀
ext := path.Ext(f)
if !tool.InSliceString(strings.ToLower(ext) , allowExts) {
return result , errors.New("文件后缀不允许:" + f)
}
//允许加入
result = append(result , f)
}
}
//数量限制
if len(result) > 300 {
return result , errors.New("文件数量不允许超过 300 个")
}
return result , nil
}
//获取应用根目录
func GetAppRootDir() string {
if rootDir , err := filepath.Abs(filepath.Dir(os.Args[0])); err != nil {
return ""
} else {
return tool.WinDir(rootDir)
}
}