qocker-miqt/main.go

893 lines
26 KiB
Go

package main
import (
"os"
"os/exec"
"runtime"
"strings"
"time"
qt "github.com/mappu/miqt/qt6"
"github.com/mappu/miqt/qt6/mainthread"
)
const AutoRefreshInterval = 1 * time.Second
func NewStatusDelegate(status string) *qt.QWidget {
mw := qt.NewQWidget2()
layout := qt.NewQHBoxLayout(mw)
layout.SetContentsMargins(4, 4, 4, 4)
layout.SetSpacing(8)
statusCircle := qt.NewQWidget2()
statusCircle.SetFixedSize2(12, 12)
var color string = "red"
if strings.Contains(status, "Up") {
color = "green"
}
statusCircle.SetStyleSheet("background-color: " + color + "; border-radius: 6px;")
statusLabel := qt.NewQLabel3(status)
layout.AddWidget(statusCircle)
layout.AddWidget(statusLabel.QWidget)
layout.AddStretch()
return mw
}
func openTerminal(container_id string) {
popupCommand("docker exec -it " + container_id + " sh -c '[ -x /bin/bash ] && exec /bin/bash || exec /bin/sh'")
}
func popupCommand(command string) {
switch runtime.GOOS {
case "darwin":
exec.Command("open", "-a", "Terminal", "--", "sh", "-c", command).Start()
case "linux":
exec.Command("x-terminal-emulator", "-e", "sh -c \""+command+"\"").Start()
case "windows":
exec.Command("start", "cmd", "/k", command).Start()
default:
panic("Opening a terminal is not supported on " + runtime.GOOS)
}
}
func openLogs(container_id string) {
popupCommand("docker logs -f " + container_id)
}
type DockerGUITab struct {
*qt.QWidget
tree *qt.QTreeWidget
search_bar *qt.QLineEdit
}
type DockerGUI struct {
*qt.QMainWindow
toolbar *qt.QToolBar
start_action *qt.QAction
stop_action *qt.QAction
remove_action *qt.QAction
create_network_action *qt.QAction
remove_network_action *qt.QAction
create_volume_action *qt.QAction
remove_volume_action *qt.QAction
terminal_action *qt.QAction
pull_image_action *qt.QAction
remove_image_action *qt.QAction
logs_action *qt.QAction
auto_refresh_checkbox *qt.QCheckBox
tab_widget *qt.QTabWidget
containers_tab *qt.QWidget
images_tab *qt.QWidget
networks_tab *qt.QWidget
volumes_tab *qt.QWidget
containers_tree *qt.QTreeWidget
images_tree *qt.QTreeWidget
networks_tree *qt.QTreeWidget
volumes_tree *qt.QTreeWidget
containers_searchbar *qt.QLineEdit
images_searchbar *qt.QLineEdit
networks_searchbar *qt.QLineEdit
volumes_searchbar *qt.QLineEdit
refresh_timer *time.Ticker
}
func NewDockerGUI() *DockerGUI {
var self DockerGUI
self.QMainWindow = qt.NewQMainWindow2()
self.SetWindowTitle("Qocker - Docker Graphical User Interface")
self.SetGeometry(100, 100, 1000, 600)
// Create central widget and layout
central_widget := qt.NewQWidget2()
self.SetCentralWidget(central_widget)
mainLayout := qt.NewQVBoxLayout(central_widget)
// Create toolbar
self.create_toolbar()
// Create tab widget
self.tab_widget = qt.NewQTabWidget2()
mainLayout.AddWidget(self.tab_widget.QWidget)
// Create tabs
self.containers_tab = qt.NewQWidget2()
self.images_tab = qt.NewQWidget2()
self.networks_tab = qt.NewQWidget2()
self.volumes_tab = qt.NewQWidget2()
self.tab_widget.AddTab(self.containers_tab, "Containers")
self.tab_widget.AddTab(self.images_tab, "Images")
self.tab_widget.AddTab(self.networks_tab, "Networks")
self.tab_widget.AddTab(self.volumes_tab, "Volumes")
// Connect tab change to toolbar update
self.tab_widget.OnCurrentChanged(self.update_toolbar_buttons)
// Create tree widgets for each tab
self.containers_tree = self.create_tree_widget("ID", "Name", "Image", "Status", "Ports")
self.images_tree = self.create_tree_widget("ID", "Repository", "Tag", "Size")
self.networks_tree = self.create_tree_widget("ID", "Name", "Driver")
self.volumes_tree = self.create_tree_widget("Name", "Driver", "Mountpoint")
self.containers_tree.OnItemDoubleClicked(func(item *qt.QTreeWidgetItem, column int) {
self.open_terminal()
})
// Add search bars
self.containers_searchbar = self.create_searchbar_widget(self.containers_tree, "Search containers...")
self.images_searchbar = self.create_searchbar_widget(self.images_tree, "Search images...")
self.networks_searchbar = self.create_searchbar_widget(self.networks_tree, "Search networks...")
self.volumes_searchbar = self.create_searchbar_widget(self.volumes_tree, "Search volumes...")
// Add tree widgets to tabs
self.setup_tab(self.containers_tab, self.containers_tree, self.containers_searchbar)
self.setup_tab(self.images_tab, self.images_tree, self.images_searchbar)
self.setup_tab(self.networks_tab, self.networks_tree, self.networks_searchbar)
self.setup_tab(self.volumes_tab, self.volumes_tree, self.volumes_searchbar)
// Create menu bar
self.create_menu_bar()
//.Setup auto-refresh
self.setup_auto_refresh()
// Populate data
self.refresh_data()
// Update toolbar buttons for initial state
self.update_toolbar_buttons(0)
// override QMainWindow.createPopupMenu
self.OnCreatePopupMenu(func(super func() *qt.QMenu) *qt.QMenu {
filtered_menu := super()
filtered_menu.RemoveAction(self.toolbar.ToggleViewAction())
return filtered_menu
})
return &self
}
func (self *DockerGUI) create_tree_widget(headers ...string) *qt.QTreeWidget {
tree := qt.NewQTreeWidget2()
tree.SetHeaderLabels(headers)
tree.SetContextMenuPolicy(qt.CustomContextMenu)
tree.OnCustomContextMenuRequested(self.show_context_menu)
tree.SetSortingEnabled(true)
header := tree.Header()
header.SetSectionResizeMode(qt.QHeaderView__Interactive)
header.SetSortIndicator(0, qt.DescendingOrder)
header.SetSortIndicatorShown(true)
header.OnSortIndicatorChanged(func(col int, order qt.SortOrder) {
self.sort_tree_widget(tree, col, order)
})
return tree
}
func (self *DockerGUI) sort_tree_widget(tree *qt.QTreeWidget, column int, order qt.SortOrder) {
tree.SortItems(column, order)
}
// Add search bar
func (self *DockerGUI) create_searchbar_widget(tree *qt.QTreeWidget, search_placeholder string) *qt.QLineEdit {
search_bar := qt.NewQLineEdit2()
search_bar.SetPlaceholderText(search_placeholder)
search_bar.OnTextChanged(func(text string) {
self.filter_tree(tree, text)
})
return search_bar
}
func (self *DockerGUI) setup_tab(tab *qt.QWidget, tree *qt.QTreeWidget, search_bar *qt.QLineEdit) {
layout := qt.NewQVBoxLayout(tab)
layout.AddWidget(search_bar.QWidget)
layout.AddWidget(tree.QWidget)
}
func (self *DockerGUI) filter_tree(tree *qt.QTreeWidget, text string) {
text = strings.ToLower(text)
for i := 0; i < tree.TopLevelItemCount(); i++ {
item := tree.TopLevelItem(i)
match := false
for j := 0; j < item.ColumnCount(); j++ {
if strings.Contains(strings.ToLower(item.Text(j)), text) {
match = true
break
}
}
item.SetHidden(!match)
}
}
func (self *DockerGUI) create_toolbar() {
self.toolbar = qt.NewQToolBar3()
self.toolbar.SetMovable(false) // Make toolbar fixed
self.AddToolBar(qt.TopToolBarArea, self.toolbar)
// Common actions
refresh_action := qt.NewQAction6(qt.QIcon_FromTheme("view-refresh"), "Refresh", self.QObject)
refresh_action.OnTriggered(self.refresh_data)
self.toolbar.AddAction(refresh_action)
// Add auto-refresh checkbox
self.auto_refresh_checkbox = qt.NewQCheckBox3("Auto-refresh")
self.auto_refresh_checkbox.SetChecked(true)
self.toolbar.AddWidget(self.auto_refresh_checkbox.QWidget)
// Add separator
self.toolbar.AddSeparator()
// Container-specific actions
self.start_action = qt.NewQAction6(qt.QIcon_FromTheme("media-playback-start"), "Start", self.QObject)
self.start_action.OnTriggered(self.start_container)
self.toolbar.AddAction(self.start_action)
self.stop_action = qt.NewQAction6(qt.QIcon_FromTheme("media-playback-stop"), "Stop", self.QObject)
self.stop_action.OnTriggered(self.stop_container)
self.toolbar.AddAction(self.stop_action)
self.remove_action = qt.NewQAction6(qt.QIcon_FromTheme("edit-delete"), "Remove", self.QObject)
self.remove_action.OnTriggered(self.remove_container)
self.toolbar.AddAction(self.remove_action)
// Image-specific actions
self.pull_image_action = qt.NewQAction6(qt.QIcon_FromTheme("download"), "Pull Image", self.QObject)
self.pull_image_action.OnTriggered(self.pull_image)
self.toolbar.AddAction(self.pull_image_action)
self.remove_image_action = qt.NewQAction6(qt.QIcon_FromTheme("edit-delete"), "Remove Image", self.QObject)
self.remove_image_action.OnTriggered(self.remove_image)
self.toolbar.AddAction(self.remove_image_action)
// Network-specific actions
self.create_network_action = qt.NewQAction6(qt.QIcon_FromTheme("list-add"), "Create Network", self.QObject)
self.create_network_action.OnTriggered(self.create_network)
self.toolbar.AddAction(self.create_network_action)
self.remove_network_action = qt.NewQAction6(qt.QIcon_FromTheme("edit-delete"), "Remove Network", self.QObject)
self.remove_network_action.OnTriggered(self.remove_network)
self.toolbar.AddAction(self.remove_network_action)
// Volume-specific actions
self.create_volume_action = qt.NewQAction6(qt.QIcon_FromTheme("list-add"), "Create Volume", self.QObject)
self.create_volume_action.OnTriggered(self.create_volume)
self.toolbar.AddAction(self.create_volume_action)
self.remove_volume_action = qt.NewQAction6(qt.QIcon_FromTheme("edit-delete"), "Remove Volume", self.QObject)
self.remove_volume_action.OnTriggered(self.remove_volume)
self.toolbar.AddAction(self.remove_volume_action)
// Add terminal action
self.terminal_action = qt.NewQAction6(qt.QIcon_FromTheme("utilities-terminal"), "Open Terminal", self.QObject)
self.terminal_action.OnTriggered(self.open_terminal)
self.toolbar.AddAction(self.terminal_action)
// Add logs action
self.logs_action = qt.NewQAction6(qt.QIcon_FromTheme("document-open"), "Open Logs", self.QObject)
self.logs_action.OnTriggered(self.open_logs)
self.toolbar.AddAction(self.logs_action)
}
func (self *DockerGUI) update_toolbar_buttons(index int) {
// Show actions based on the current tab
// Containers tab
self.start_action.SetVisible(index == 0)
self.stop_action.SetVisible(index == 0)
self.remove_action.SetVisible(index == 0)
self.terminal_action.SetVisible(index == 0)
self.logs_action.SetVisible(index == 0)
// Images tab
self.pull_image_action.SetVisible(index == 1)
self.remove_image_action.SetVisible(index == 1)
// Networks tab
self.create_network_action.SetVisible(index == 2)
self.remove_network_action.SetVisible(index == 2)
// Volumes tab
self.create_volume_action.SetVisible(index == 3)
self.remove_volume_action.SetVisible(index == 3)
}
func (self *DockerGUI) update_visible_tabs(index int) {
for i := 0; i < self.tab_widget.Count(); i++ {
self.tab_widget.TabBar().SetTabVisible(i, (i == index))
}
}
func (self *DockerGUI) create_menu_bar() {
menubar := self.MenuBar()
file_menu := menubar.AddMenuWithTitle("&File")
exit_action := qt.NewQAction5("E&xit", self.QObject)
exit_action.OnTriggered(func() {
self.Close()
})
file_menu.AddAction(exit_action)
docker_menu := menubar.AddMenuWithTitle("&Docker")
refresh_action := qt.NewQAction5("&Refresh", self.QObject)
refresh_action.OnTriggered(self.refresh_data)
docker_menu.AddAction(refresh_action)
}
func (self *DockerGUI) show_context_menu(position *qt.QPoint) {
context_menu := qt.NewQMenu2()
current_tab := self.tab_widget.CurrentWidget()
// Add refresh action to context menu
refresh_action := qt.NewQAction5("&Refresh", self.QObject)
refresh_action.OnTriggered(self.refresh_data)
context_menu.AddAction(refresh_action)
context_menu.AddSeparator()
if current_tab == self.containers_tab {
terminal_action := qt.NewQAction5("&Terminal", self.QObject)
terminal_action.OnTriggered(func() { self.handle_action("Terminal") })
context_menu.AddAction(terminal_action)
logs_action := qt.NewQAction5("&Logs", self.QObject)
logs_action.OnTriggered(func() { self.open_logs() })
context_menu.AddAction(logs_action)
context_menu.AddSeparator()
start_action := qt.NewQAction5("&Start", self.QObject)
start_action.OnTriggered(func() { self.handle_action("Start") })
context_menu.AddAction(start_action)
stop_action := qt.NewQAction5("S&top", self.QObject)
stop_action.OnTriggered(func() { self.handle_action("Stop") })
context_menu.AddAction(stop_action)
remove_action := qt.NewQAction5("Remo&ve", self.QObject)
remove_action.OnTriggered(func() { self.handle_action("Remove") })
context_menu.AddAction(remove_action)
} else if current_tab == self.images_tab {
pull_action := qt.NewQAction5("&Pull", self.QObject)
pull_action.OnTriggered(self.pull_image)
context_menu.AddAction(pull_action)
context_menu.AddSeparator()
remove_action := qt.NewQAction5("Remo&ve", self.QObject)
remove_action.OnTriggered(self.remove_image)
context_menu.AddAction(remove_action)
} else if current_tab == self.networks_tab {
remove_action := qt.NewQAction5("Remo&ve", self.QObject)
remove_action.OnTriggered(func() { self.handle_action("Remove") })
context_menu.AddAction(remove_action)
} else if current_tab == self.volumes_tab {
remove_action := qt.NewQAction5("Remo&ve", self.QObject)
remove_action.OnTriggered(func() { self.handle_action("Remove") })
context_menu.AddAction(remove_action)
}
context_menu.ExecWithPos(current_tab.MapToGlobalWithQPoint(position))
}
func (self *DockerGUI) setup_auto_refresh() {
self.refresh_timer = time.NewTicker(AutoRefreshInterval)
go func() {
for {
_, ok := <-self.refresh_timer.C
if !ok {
return
}
mainthread.Wait(func() {
if !self.auto_refresh_checkbox.IsChecked() {
return
}
self.refresh_data()
})
}
}()
}
func (self *DockerGUI) handle_action(action string) {
current_tab := self.tab_widget.CurrentWidget()
if current_tab == self.containers_tab {
selected_items := self.containers_tree.SelectedItems()
if len(selected_items) == 0 {
return
}
container_id := selected_items[0].Text(0)
if action == "Terminal" {
self.open_terminal()
} else if action == "Start" {
exec.Command("docker", "start", container_id).Run()
} else if action == "Stop" {
exec.Command("docker", "stop", container_id).Run()
} else if action == "Remove" {
exec.Command("docker", "rm", "-f", container_id).Run()
}
} else if current_tab == self.networks_tab {
selected_items := self.networks_tree.SelectedItems()
if len(selected_items) == 0 {
return
}
network_id := selected_items[0].Text(0)
if action == "Remove" {
exec.Command("docker", "network", "rm", network_id).Run()
}
} else if current_tab == self.volumes_tab {
selected_items := self.volumes_tree.SelectedItems()
if len(selected_items) == 0 {
return
}
volume_name := selected_items[0].Text(0)
if action == "Remove" {
exec.Command("docker", "volume", "rm", volume_name).Run()
}
}
self.refresh_data()
}
func (self *DockerGUI) refresh_data() {
self.refresh_containers()
self.refresh_images()
self.refresh_networks()
self.refresh_volumes()
}
func (self *DockerGUI) refresh_containers() {
scroll_position := self.containers_tree.VerticalScrollBar().Value()
selected_items := self.get_selected_items(self.containers_tree)
self.containers_tree.Clear()
output, err := exec.Command("docker", "ps", "-a", "--format", "{{.ID}}\\t{{.Names}}\\t{{.Image}}\\t{{.Status}}\\t{{.Ports}}").Output()
if err != nil {
panic(err)
}
containers := strings.Split(strings.TrimSpace(string(output)), "\n")
for _, container := range containers {
parts := strings.Split(container, "\t")
if len(parts) == 1 {
continue
}
id := parts[0]
name := parts[1]
image := parts[2]
status := parts[3]
ports := ""
if len(parts) > 4 {
ports = parts[4]
}
item := qt.NewQTreeWidgetItem2([]string{id, name, image, "", ports}) // Empty string for status column
status_widget := NewStatusDelegate(status)
self.containers_tree.AddTopLevelItem(item)
self.containers_tree.SetItemWidget(item, 3, status_widget)
}
self.filter_tree(self.containers_tree, self.containers_searchbar.Text())
self.restore_selection(self.containers_tree, selected_items)
self.containers_tree.VerticalScrollBar().SetValue(scroll_position)
}
func (self *DockerGUI) refresh_images() {
scroll_position := self.images_tree.VerticalScrollBar().Value()
selected_items := self.get_selected_items(self.images_tree)
self.images_tree.Clear()
output, err := exec.Command("docker", "images", "--format", "{{.ID}}\\t{{.Repository}}\\t{{.Tag}}\\t{{.Size}}").Output()
if err != nil {
panic(err)
}
images := strings.Split(strings.TrimSpace(string(output)), "\n")
for _, image := range images {
parts := strings.Split(image, "\t")
if len(parts) == 1 {
continue
}
id := parts[0]
repository := parts[1]
tag := parts[2]
size := parts[3]
item := qt.NewQTreeWidgetItem2([]string{id, repository, tag, size})
self.images_tree.AddTopLevelItem(item)
}
self.filter_tree(self.images_tree, self.images_searchbar.Text())
self.restore_selection(self.images_tree, selected_items)
self.images_tree.VerticalScrollBar().SetValue(scroll_position)
}
func (self *DockerGUI) refresh_networks() {
scroll_position := self.networks_tree.VerticalScrollBar().Value()
selected_items := self.get_selected_items(self.networks_tree)
self.networks_tree.Clear()
output, err := exec.Command("docker", "network", "ls", "--format", "{{.ID}}\\t{{.Name}}\\t{{.Driver}}").Output()
if err != nil {
panic(err)
}
networks := strings.Split(strings.TrimSpace(string(output)), "\n")
for _, network := range networks {
parts := strings.Split(network, "\t")
if len(parts) == 1 {
continue
}
id := parts[0]
name := parts[1]
driver := parts[2]
item := qt.NewQTreeWidgetItem2([]string{id, name, driver})
self.networks_tree.AddTopLevelItem(item)
}
self.filter_tree(self.networks_tree, self.networks_searchbar.Text())
self.restore_selection(self.networks_tree, selected_items)
self.networks_tree.VerticalScrollBar().SetValue(scroll_position)
}
func (self *DockerGUI) refresh_volumes() {
scroll_position := self.volumes_tree.VerticalScrollBar().Value()
selected_items := self.get_selected_items(self.volumes_tree)
self.volumes_tree.Clear()
output, err := exec.Command("docker", "volume", "ls", "--format", "{{.Name}}\\t{{.Driver}}\\t{{.Mountpoint}}").Output()
if err != nil {
panic(err)
}
volumes := strings.Split(strings.TrimSpace(string(output)), "\n")
for _, volume := range volumes {
parts := strings.Split(volume, "\t")
if len(parts) == 1 {
continue
}
name := parts[0]
driver := parts[1]
mountpoint := parts[2]
item := qt.NewQTreeWidgetItem2([]string{name, driver, mountpoint})
self.volumes_tree.AddTopLevelItem(item)
}
self.filter_tree(self.volumes_tree, self.volumes_searchbar.Text())
self.restore_selection(self.volumes_tree, selected_items)
self.volumes_tree.VerticalScrollBar().SetValue(scroll_position)
}
func (self *DockerGUI) get_selected_items(tree *qt.QTreeWidget) []string {
selItems := tree.SelectedItems()
ret := make([]string, 0, len(selItems))
for _, itm := range selItems {
ret = append(ret, itm.Text(0))
}
return ret
}
func (self *DockerGUI) restore_selection(tree *qt.QTreeWidget, selected_items []string) {
rmatch := map[string]struct{}{}
for _, itm := range selected_items {
rmatch[itm] = struct{}{}
}
for i := 0; i < tree.TopLevelItemCount(); i++ {
item := tree.TopLevelItem(i)
if _, ok := rmatch[item.Text(0)]; ok {
item.SetSelected(true)
}
}
}
func (self *DockerGUI) start_container() {
selected_items := self.containers_tree.SelectedItems()
if len(selected_items) == 0 {
qt.QMessageBox_Warning(self.QWidget, "No Selection", "Please select a container to start.")
return
}
for _, item := range selected_items {
container_id := item.Text(0)
err := exec.Command("docker", "start", container_id).Wait()
if err != nil {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to start container "+container_id+": "+err.Error())
}
}
self.refresh_containers()
}
func (self *DockerGUI) stop_container() {
selected_items := self.containers_tree.SelectedItems()
if len(selected_items) == 0 {
qt.QMessageBox_Warning(self.QWidget, "No Selection", "Please select a container to stop.")
return
}
for _, item := range selected_items {
container_id := item.Text(0)
err := exec.Command("docker", "stop", container_id).Run()
if err != nil {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to stop container "+container_id+": "+err.Error())
}
}
self.refresh_containers()
}
func (self *DockerGUI) remove_container() {
selected_items := self.containers_tree.SelectedItems()
if len(selected_items) == 0 {
qt.QMessageBox_Warning(self.QWidget, "No Selection", "Please select a container to remove.")
return
}
for _, item := range selected_items {
container_id := item.Text(0)
reply := qt.QMessageBox_Question5(self.QWidget,
"Confirm Removal",
"Are you sure you want to remove container "+container_id+"?",
qt.QMessageBox__Yes|qt.QMessageBox__No,
qt.QMessageBox__No,
)
if reply != qt.QMessageBox__Yes {
continue
}
err := exec.Command("docker", "rm", "-f", container_id).Run()
if err != nil {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to remove container "+container_id+": "+err.Error())
}
}
self.refresh_containers()
}
func (self *DockerGUI) pull_image() {
image_name := qt.QInputDialog_GetText(self.QWidget, "Pull Image", "Enter image name (e.g., ubuntu:latest):")
if image_name == "" {
return
}
err := exec.Command("docker", "pull", image_name).Run()
if err == nil {
qt.QMessageBox_Information(self.QWidget, "Success", "Image \""+image_name+"\" pulled successfully.")
} else {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to pull image: "+err.Error())
}
self.refresh_images()
}
func (self *DockerGUI) remove_image() {
selected_items := self.images_tree.SelectedItems()
if len(selected_items) == 0 {
qt.QMessageBox_Warning(self.QWidget, "No Selection", "Please select an image to remove.")
return
}
for _, item := range selected_items {
image_id := item.Text(0)
reply := qt.QMessageBox_Question5(self.QWidget, "Confirm Removal",
"Are you sure you want to remove image "+image_id+"?",
qt.QMessageBox__Yes|qt.QMessageBox__No,
qt.QMessageBox__No,
)
if reply != qt.QMessageBox__Yes {
continue
}
err := exec.Command("docker", "rmi", image_id).Run()
if err == nil {
qt.QMessageBox_Information(self.QWidget, "Success", "Image \""+image_id+"\" removed successfully.")
} else {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to remove image "+image_id+": "+err.Error())
}
}
self.refresh_images()
}
func (self *DockerGUI) create_network() {
network_name := qt.QInputDialog_GetText(self.QWidget, "Create Network", "Enter network name:")
if network_name == "" {
return
}
err := exec.Command("docker", "network", "create", network_name).Run()
if err == nil {
qt.QMessageBox_Information(self.QWidget, "Success", "Network \""+network_name+"\" created successfully.")
} else {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to create network: "+err.Error())
}
self.refresh_networks()
}
func (self *DockerGUI) remove_network() {
selected_items := self.networks_tree.SelectedItems()
if len(selected_items) == 0 {
qt.QMessageBox_Warning(self.QWidget, "No Selection", "Please select a network to remove.")
return
}
for _, item := range selected_items {
network_name := item.Text(1) // Assuming the network name is in the second column
reply := qt.QMessageBox_Question5(self.QWidget, "Confirm Removal",
"Are you sure you want to remove network "+network_name+"?",
qt.QMessageBox__Yes|qt.QMessageBox__No,
qt.QMessageBox__No,
)
if reply != qt.QMessageBox__Yes {
continue
}
err := exec.Command("docker", "network", "rm", network_name).Run()
if err == nil {
qt.QMessageBox_Information(self.QWidget, "Success", "Network \""+network_name+"\" removed successfully.")
} else {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to remove network "+network_name+": "+err.Error())
}
}
self.refresh_networks()
}
func (self *DockerGUI) create_volume() {
volume_name := qt.QInputDialog_GetText(self.QWidget, "Create Volume", "Enter volume name:")
if volume_name == "" {
return
}
err := exec.Command("docker", "volume", "create", volume_name).Run()
if err == nil {
qt.QMessageBox_Information(self.QWidget, "Success", "Volume \""+volume_name+"\" created successfully.")
} else {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to create volume "+volume_name+": "+err.Error())
}
self.refresh_volumes()
}
func (self *DockerGUI) remove_volume() {
selected_items := self.volumes_tree.SelectedItems()
if len(selected_items) == 0 {
qt.QMessageBox_Warning(self.QWidget, "No Selection", "Please select a volume to remove.")
return
}
for _, item := range selected_items {
volume_name := item.Text(0) // Assuming the volume name is in the first column
reply := qt.QMessageBox_Question5(self.QWidget, "Confirm Removal",
"Are you sure you want to remove volume "+volume_name+"?",
qt.QMessageBox__Yes|qt.QMessageBox__No,
qt.QMessageBox__No,
)
if reply != qt.QMessageBox__Yes {
continue
}
err := exec.Command("docker", "volume", "rm", volume_name).Run()
if err == nil {
qt.QMessageBox_Information(self.QWidget, "Success", "Volume \""+volume_name+"\" removed successfully.")
} else {
qt.QMessageBox_Critical(self.QWidget, "Error", "Failed to remove volume "+volume_name+": "+err.Error())
}
}
self.refresh_volumes()
}
func (self *DockerGUI) open_terminal() {
selected_items := self.containers_tree.SelectedItems()
if len(selected_items) == 0 {
qt.QMessageBox_Warning(self.QWidget, "No Selection", "Please select a container to open terminal.")
return
}
container_id := selected_items[0].Text(0)
openTerminal(container_id)
}
func (self *DockerGUI) show_terminal_error(error_message string) {
qt.QMessageBox_Critical(self.QWidget, "Error", error_message)
}
func (self *DockerGUI) open_logs() {
selected_items := self.containers_tree.SelectedItems()
if len(selected_items) == 0 {
qt.QMessageBox_Warning(self.QWidget, "No Selection", "Please select a container to open logs.")
return
}
container_id := selected_items[0].Text(0)
openLogs(container_id)
}
func (self *DockerGUI) show_logs_error(error_message string) {
qt.QMessageBox_Critical(self.QWidget, "Error", error_message)
}
func main() {
qt.NewQApplication(os.Args)
window := NewDockerGUI()
window.Show()
os.Exit(qt.QApplication_Exec())
}