This commit is contained in:
2026-04-04 00:09:02 +08:00
commit 38e896363e
117 changed files with 119311 additions and 0 deletions

View File

@@ -0,0 +1,489 @@
package main
import (
"fmt"
"log"
"strconv"
"strings"
"time"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func createInstalledPkgsTab(server outputStruct) *fyne.Container {
searchPkgEntry := widget.NewEntry()
searchPkgEntry.SetPlaceHolder("Поиск пакетов ...")
filteredPackages := server.InstalledPackages
installedPackagesList := widget.NewList(
func() int {
return len(filteredPackages)
},
func() fyne.CanvasObject {
return container.NewHBox(
widget.NewLabel("Пакет"),
widget.NewLabel("Версия"),
)
},
func(id widget.ListItemID, obj fyne.CanvasObject) {
hbox := obj.(*fyne.Container)
pkg := filteredPackages[id]
nameLabel := hbox.Objects[0].(*widget.Label)
versionLabel := hbox.Objects[1].(*widget.Label)
nameLabel.SetText(pkg.Name)
versionLabel.SetText(pkg.Version)
versionLabel.TextStyle = fyne.TextStyle{Monospace: true}
},
)
searchPkgEntry.OnChanged = func(text string) {
if text == "" {
filteredPackages = server.InstalledPackages
} else {
filtered := []installedPackage{}
lowerText := strings.ToLower(text)
for _, pkg := range server.InstalledPackages {
if strings.Contains(strings.ToLower(pkg.Name), lowerText) ||
strings.Contains(strings.ToLower(pkg.Version), lowerText) {
filtered = append(filtered, pkg)
}
}
filteredPackages = filtered
}
installedPackagesList.Refresh()
}
installedPkgsTab := container.NewBorder(
container.NewVBox(
searchPkgEntry,
widget.NewSeparator(),
),
nil, nil, nil,
container.NewScroll(installedPackagesList),
)
return installedPkgsTab
}
func createFsInfoTab(server outputStruct) *fyne.Container {
searchFsInfoEntry := widget.NewEntry()
searchFsInfoEntry.SetPlaceHolder("Поиск монтирований...")
filteredFs := server.FsInformations
fsInfoList := widget.NewList(
func() int {
return len(filteredFs)
},
func() fyne.CanvasObject {
return container.NewHBox(
widget.NewLabel("Устройство"),
widget.NewLabel("Путь монтирования"),
widget.NewLabel("Размер"),
widget.NewLabel("Свободно"),
)
},
func(id widget.ListItemID, obj fyne.CanvasObject) {
hbox := obj.(*fyne.Container)
fs := filteredFs[id]
deviceLabel := hbox.Objects[0].(*widget.Label)
pathLabel := hbox.Objects[1].(*widget.Label)
sizeLabel := hbox.Objects[2].(*widget.Label)
freeLabel := hbox.Objects[3].(*widget.Label)
deviceLabel.SetText(fs.MountPointDevice)
pathLabel.SetText(fs.MountPointOsPath)
sizeLabel.SetText(strconv.Itoa(int(fs.MountPointSize)))
freeLabel.SetText(strconv.Itoa(int(fs.MountPointFree)))
freeLabel.TextStyle.Bold = true
},
)
searchFsInfoEntry.OnChanged = func(text string) {
if text == "" {
filteredFs = server.FsInformations
} else {
filtered := []fsInfo{}
lowerText := strings.ToLower(text)
for _, fs := range server.FsInformations {
if strings.Contains(strings.ToLower(fs.MountPointDevice), lowerText) ||
strings.Contains(strings.ToLower(fs.MountPointOsPath), lowerText) {
filtered = append(filtered, fs)
}
}
filteredFs = filtered
}
fsInfoList.Refresh()
}
fsInfoTab := container.NewBorder(
container.NewVBox(
searchFsInfoEntry,
widget.NewSeparator(),
), nil, nil, nil,
container.NewScroll(fsInfoList),
)
return fsInfoTab
}
// func createCpuTab(server outputStruct) *fyne.Container {
// searchCpuEntry := widget.NewEntry()
// searchCpuEntry.SetPlaceHolder("ЦПУ...")
// filteredCpu := server.Cpu.Model
// cpuList := widget.NewList(
// func() int {
// return len(filteredCpu)
// },
// func() fyne.CanvasObject {
// return container.NewHBox(
// widget.NewLabel("Модель"),
// )
// },
// func(id widget.ListItemID, obj fyne.CanvasObject) {
// hbox := obj.(*fyne.Container)
// cpu := filteredCpu[id]
// modelLabel := hbox.Objects[0].(*widget.Label)
// modelLabel.SetText(cpu)
// },
// )
// searchCpuEntry.OnChanged = func(text string) {
// if text == "" {
// filteredCpu = server.Cpu.Model
// } else {
// filtered := cpu{}
// lowerText := strings.ToLower(text)
// for _, c := range server.Cpu.Model {
// if strings.Contains(strings.ToLower(c), lowerText) {
// filtered.Model = append(filtered.Model, c)
// }
// }
// filteredCpu = filtered.Model
// }
// cpuList.Refresh()
// }
// cpuTab := container.NewBorder(
// container.NewVBox(
// searchCpuEntry,
// widget.NewSeparator(),
// ), nil, nil, nil,
// container.NewScroll(cpuList),
// )
// return cpuTab
// }
func createCpuTab(server outputStruct) *fyne.Container {
searchEntry := widget.NewEntry()
searchEntry.SetPlaceHolder("Поиск ...")
filteredEntries := server.Cpus
list := widget.NewList(
func() int {
return len(filteredEntries)
},
func() fyne.CanvasObject {
return container.NewVBox(
widget.NewLabel("VendorID,CpuFamily,Model,ModelName"),
widget.NewLabel("Stepping,Microcode,CpuMhz,CacheSize"),
widget.NewLabel("PhysicalId,CpuCores,Fpu,FpuException,Wp"),
widget.NewLabel("Flags"),
widget.NewLabel("Bugs"),
widget.NewLabel("Bogomips,TlbSize,ClflushSize"),
widget.NewLabel("CacheAlignment,AddressSize,PowerManagement"),
)
},
func(id widget.ListItemID, obj fyne.CanvasObject) {
box := obj.(*fyne.Container)
e := filteredEntries[id]
label0 := box.Objects[0].(*widget.Label)
label1 := box.Objects[1].(*widget.Label)
label2 := box.Objects[2].(*widget.Label)
label3 := box.Objects[3].(*widget.Label)
label4 := box.Objects[4].(*widget.Label)
label5 := box.Objects[5].(*widget.Label)
label6 := box.Objects[6].(*widget.Label)
label0.SetText(fmt.Sprintf("VendorId: %s, CpuFamily: %s, Model: %s, ModelName: %s", e.VendorId, e.CpuFamily, e.Model, e.ModelName))
label1.SetText(fmt.Sprintf("Stepping: %s, Microcode: %s, CpuMhz: %s, CacheSize: %s", e.Stepping, e.Microcode, e.CpuMhz, e.CacheSize))
label2.SetText(fmt.Sprintf("PhysicalId: %s, CpuCores: %s", e.PhysicalId, e.CpuCores))
label3.SetText(fmt.Sprintf("Flags: %s", e.Flags))
label4.SetText(fmt.Sprintf("Bugs: %s", e.Bugs))
label5.SetText(fmt.Sprintf("Bogomips: %s, TlbSize: %s, ClflushSize: %s", e.Bogomips, e.TlbSize, e.ClflushSize))
label6.SetText(fmt.Sprintf("CacheAlignment: %s, AddressSize: %s, PowerManagement: %s", e.CacheAlignment, e.AddressSize, e.PowerManagement))
},
)
searchEntry.OnChanged = func(textRaw string) {
if textRaw == "" {
filteredEntries = server.Cpus
} else {
filtered := []cpu{}
text := strings.ToLower(textRaw)
for _, elem := range server.Cpus {
if strings.Contains(strings.ToLower(elem.Flags), text) {
filtered = append(filtered, elem)
}
}
filteredEntries = filtered
}
list.Refresh()
}
tab := container.NewBorder(
container.NewVBox(
searchEntry,
widget.NewSeparator(),
), nil, nil, nil,
container.NewScroll(list),
)
return tab
}
func createInternetRequiredTab(server outputStruct) *fyne.Container {
searchEntry := widget.NewEntry()
searchEntry.SetPlaceHolder("Поиск ...")
filteredEntries := server.InternetRequired
list := widget.NewList(
func() int {
return len(filteredEntries)
},
func() fyne.CanvasObject {
return container.NewVBox(
// widget.NewCard("Title", "Subtitle", widget.NewLabel("content")),
widget.NewLabel("name"),
widget.NewLabel("ip_list"),
widget.NewLabel("http+https"),
)
},
func(id widget.ListItemID, obj fyne.CanvasObject) {
box := obj.(*fyne.Container)
e := filteredEntries[id]
label0 := box.Objects[0].(*widget.Label)
label1 := box.Objects[1].(*widget.Label)
label2 := box.Objects[2].(*widget.Label)
label0.SetText(e.Name)
label0.TextStyle.Bold = true
label1.SetText(e.IpList)
label1.Selectable = true
label2.SetText(fmt.Sprintf("HTTP: %s HTTPS: %s", e.Http, e.Https))
label2.Selectable = true
// card := box.Objects[0].(*widget.Card)
// card.SetTitle(e.Name)
// card.SetSubTitle(e.IpList)
// card.SetContent(widget.NewLabel(fmt.Sprintf("HTTP: %s HTTPS: %s", e.Http, e.Https)))
},
)
searchEntry.OnChanged = func(textRaw string) {
if textRaw == "" {
filteredEntries = server.InternetRequired
} else {
filtered := []internetResource{}
text := strings.ToLower(textRaw)
for _, elem := range server.InternetRequired {
if strings.Contains(strings.ToLower(elem.Name), text) {
filtered = append(filtered, elem)
}
}
filteredEntries = filtered
}
list.Refresh()
}
tab := container.NewBorder(
container.NewVBox(
searchEntry,
widget.NewSeparator(),
), nil, nil, nil,
container.NewScroll(list),
)
return tab
}
func createSecSetTab(server outputStruct) *widget.Label {
if strings.Contains(server.OperatingSystem.OsRelease, "Alma") {
return widget.NewLabel(fmt.Sprintf("Selinux :: %s", server.SecSetAlma.Selinux))
} else if strings.Contains(server.OperatingSystem.OsRelease, "Ubuntu") {
return widget.NewLabel(fmt.Sprintf("Apparmor :: %s", server.SecSetUbuntu.Apparmor))
} else {
return widget.NewLabel(fmt.Sprintf("Apparmor\t%s\nAstraAdmin\t%s\nDigsig\t%s\nИнтерпретаторы\t%s\nmac\t%s\nmic\t%s\nnochmodx\t%s\nparsec\t%s\nselinux\t%s\nsudo control\t%s\nsudoers astra admin\t%s\nsudoers sudo\t%s", server.SecSetALSE.Apparmor, server.SecSetALSE.AstraAdmin, server.SecSetALSE.Digsig, server.SecSetALSE.Interpret, server.SecSetALSE.Mac, server.SecSetALSE.Mic, server.SecSetALSE.Nochmodx, server.SecSetALSE.Parsec, server.SecSetALSE.Selinux, server.SecSetALSE.Sudo, server.SecSetALSE.SudoersAstraAdmin, server.SecSetALSE.SudoersSudo))
}
}
// Это делал DeepSeek оно криво, но работает. Оставлю это так, потому что всё равно планирую не использовать больше fyne
func createJournalTab(server outputStruct) *fyne.Container {
searchJrlEntry := widget.NewEntry()
searchJrlEntry.SetPlaceHolder("Поиск событий ...")
filteredEvents := server.JournalctlEntries
// Создаем список
journalctlEntriesList := widget.NewList(
func() int {
return len(filteredEvents)
},
func() fyne.CanvasObject {
// Возвращаем кастомный виджет
return NewJournalListItem(journalctlEntry{})
},
func(id widget.ListItemID, obj fyne.CanvasObject) {
// Обновляем виджет
widget := obj.(*JournalListItem)
widget.Update(filteredEvents[id])
},
)
searchJrlEntry.OnChanged = func(text string) {
if text == "" {
filteredEvents = server.JournalctlEntries
} else {
filtered := []journalctlEntry{}
lowerText := strings.ToLower(text)
for _, ev := range server.JournalctlEntries {
if strings.Contains(strings.ToLower(ev.CommandLine), lowerText) ||
strings.Contains(strings.ToLower(ev.CommandName), lowerText) ||
strings.Contains(strings.ToLower(ev.SyslogIdentifier), lowerText) ||
strings.Contains(strings.ToLower(ev.Message), lowerText) {
filtered = append(filtered, ev)
}
}
filteredEvents = filtered
}
journalctlEntriesList.Refresh()
}
journalctlEntriesTab := container.NewBorder(
container.NewVBox(
searchJrlEntry,
widget.NewSeparator(),
), nil, nil, nil,
container.NewScroll(journalctlEntriesList),
)
return journalctlEntriesTab
}
// func createJournalTab(server outputStruct) *fyne.Container {
// searchJrlEntry := widget.NewEntry()
// searchJrlEntry.SetPlaceHolder("Поиск событий ...")
// filteredEvents := server.JournalctlEntries
// journalctlEntriesList := widget.NewList(
// func() int {
// return len(filteredEvents)
// },
// func() fyne.CanvasObject {
// label := widget.NewLabel("entry")
// label.Wrapping = fyne.TextWrapBreak
// // label.Resize(fyne.Size{Height: 50})
// return container.NewVBox(
// label,
// // widget.NewSeparator(),
// )
// },
// func(id widget.ListItemID, obj fyne.CanvasObject) {
// vbox := obj.(*fyne.Container)
// event := filteredEvents[id]
// eventEntry := vbox.Objects[0].(*widget.Label)
// eventEntry.SetText(fmt.Sprintf("%s :: %s :: %s :: %s :: %s", event.Timestamp, event.CommandLine, event.CommandName, event.SyslogIdentifier, event.Message))
// eventEntry.Selectable = true
// eventEntry.Wrapping = fyne.TextWrapBreak
// var doubleHeight fyne.Size
// doubleHeight.Height = 72.0
// if eventEntry.Size().Height >= 36.0 {
// eventEntry.Resize(doubleHeight)
// }
// // eventEntry.Truncation = fyne.TextTruncateClip
// },
// )
// searchJrlEntry.OnChanged = func(text string) {
// if text == "" {
// filteredEvents = server.JournalctlEntries
// } else {
// filtered := []journalctlEntry{}
// lowerText := strings.ToLower(text)
// for _, ev := range server.JournalctlEntries {
// if strings.Contains(strings.ToLower(ev.CommandLine), lowerText) || strings.Contains(strings.ToLower(ev.CommandName), lowerText) || strings.Contains(strings.ToLower(ev.SyslogIdentifier), lowerText) || strings.Contains(strings.ToLower(ev.Message), lowerText) {
// filtered = append(filtered, ev)
// }
// }
// filteredEvents = filtered
// }
// journalctlEntriesList.Refresh()
// }
// journalctlEntriesTab := container.NewBorder(
// container.NewVBox(
// searchJrlEntry,
// widget.NewSeparator(),
// ), nil, nil, nil,
// container.NewScroll(journalctlEntriesList),
// )
// return journalctlEntriesTab
// }
func createRootHistoryTab(server outputStruct) *fyne.Container {
searchEntry := widget.NewEntry()
searchEntry.SetPlaceHolder("Поиск ...")
filteredEntries := server.RootHistory
list := widget.NewList(
func() int {
return len(filteredEntries)
},
func() fyne.CanvasObject {
return container.NewVBox(
widget.NewLabel("template"),
)
},
func(id widget.ListItemID, obj fyne.CanvasObject) {
box := obj.(*fyne.Container)
e := filteredEntries[id]
fileName := box.Objects[0].(*widget.Label)
timeExec := ""
if len(e.ExecutionTime) != 0 {
timeInt64, err := strconv.ParseInt(e.ExecutionTime, 10, 64)
if err != nil {
log.Println(err)
timeExec = e.ExecutionTime
} else {
timeExec = time.Unix(timeInt64, 0).String()
}
}
fileName.SetText(fmt.Sprintf("%d %s %s", e.Id, timeExec, e.Command))
fileName.Selectable = true
},
)
searchEntry.OnChanged = func(text string) {
if text == "" {
filteredEntries = server.RootHistory
} else {
var filtered []rootHistoryCommand
lText := strings.ToLower(text)
for _, elem := range server.RootHistory {
if strings.Contains(strings.ToLower(elem.Command), lText) {
filtered = append(filtered, elem)
}
}
filteredEntries = filtered
}
list.Refresh()
}
tab := container.NewBorder(
container.NewVBox(
searchEntry,
widget.NewSeparator(),
), nil, nil, nil,
container.NewScroll(list),
)
return tab
}