Merge pull request #6 from rodrigopedra/master

Verify if any volumes are present
This commit is contained in:
Salem Yaslem 2024-09-24 12:46:41 +03:00 committed by GitHub
commit 0d8c73f80c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 36 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/.idea
/venv

60
main.py
View File

@ -13,14 +13,14 @@ class StatusDelegate(QWidget):
layout = QHBoxLayout(self) layout = QHBoxLayout(self)
layout.setContentsMargins(4, 4, 4, 4) layout.setContentsMargins(4, 4, 4, 4)
layout.setSpacing(8) layout.setSpacing(8)
self.status_circle = QWidget() self.status_circle = QWidget()
self.status_circle.setFixedSize(12, 12) self.status_circle.setFixedSize(12, 12)
color = QColor('green') if 'Up' in status else QColor('red') color = QColor('green') if 'Up' in status else QColor('red')
self.status_circle.setStyleSheet(f"background-color: {color.name()}; border-radius: 6px;") self.status_circle.setStyleSheet(f"background-color: {color.name()}; border-radius: 6px;")
self.status_label = QLabel(status) self.status_label = QLabel(status)
layout.addWidget(self.status_circle) layout.addWidget(self.status_circle)
layout.addWidget(self.status_label) layout.addWidget(self.status_label)
layout.addStretch() layout.addStretch()
@ -85,7 +85,7 @@ class DockerGUI(QMainWindow):
self.images_tree = self.create_tree_widget(["ID", "Repository", "Tag", "Size"]) self.images_tree = self.create_tree_widget(["ID", "Repository", "Tag", "Size"])
self.networks_tree = self.create_tree_widget(["ID", "Name", "Driver"]) self.networks_tree = self.create_tree_widget(["ID", "Name", "Driver"])
self.volumes_tree = self.create_tree_widget(["Name", "Driver", "Mountpoint"]) self.volumes_tree = self.create_tree_widget(["Name", "Driver", "Mountpoint"])
self.containers_tree.itemDoubleClicked.connect(self.open_terminal) self.containers_tree.itemDoubleClicked.connect(self.open_terminal)
# Add tree widgets to tabs # Add tree widgets to tabs
@ -127,7 +127,7 @@ class DockerGUI(QMainWindow):
search_bar.setPlaceholderText(search_placeholder) search_bar.setPlaceholderText(search_placeholder)
search_bar.textChanged.connect(lambda text: self.filter_tree(tree, text)) search_bar.textChanged.connect(lambda text: self.filter_tree(tree, text))
layout.addWidget(search_bar) layout.addWidget(search_bar)
layout.addWidget(tree) layout.addWidget(tree)
def filter_tree(self, tree, text): def filter_tree(self, tree, text):
@ -185,7 +185,7 @@ class DockerGUI(QMainWindow):
self.remove_network_action = QAction(QIcon.fromTheme("edit-delete"), "Remove Network", self) self.remove_network_action = QAction(QIcon.fromTheme("edit-delete"), "Remove Network", self)
self.remove_network_action.triggered.connect(self.remove_network) self.remove_network_action.triggered.connect(self.remove_network)
self.toolbar.addAction(self.remove_network_action) self.toolbar.addAction(self.remove_network_action)
# Volume-specific actions # Volume-specific actions
self.create_volume_action = QAction(QIcon.fromTheme("list-add"), "Create Volume", self) self.create_volume_action = QAction(QIcon.fromTheme("list-add"), "Create Volume", self)
self.create_volume_action.triggered.connect(self.create_volume) self.create_volume_action.triggered.connect(self.create_volume)
@ -194,7 +194,7 @@ class DockerGUI(QMainWindow):
self.remove_volume_action = QAction(QIcon.fromTheme("edit-delete"), "Remove Volume", self) self.remove_volume_action = QAction(QIcon.fromTheme("edit-delete"), "Remove Volume", self)
self.remove_volume_action.triggered.connect(self.remove_volume) self.remove_volume_action.triggered.connect(self.remove_volume)
self.toolbar.addAction(self.remove_volume_action) self.toolbar.addAction(self.remove_volume_action)
# Add terminal action # Add terminal action
self.terminal_action = QAction(QIcon.fromTheme("utilities-terminal"), "Open Terminal", self) self.terminal_action = QAction(QIcon.fromTheme("utilities-terminal"), "Open Terminal", self)
self.terminal_action.triggered.connect(self.open_terminal) self.terminal_action.triggered.connect(self.open_terminal)
@ -269,7 +269,7 @@ class DockerGUI(QMainWindow):
stop_action.triggered.connect(lambda: self.handle_action("Stop")) stop_action.triggered.connect(lambda: self.handle_action("Stop"))
remove_action = QAction("Remove", self) remove_action = QAction("Remove", self)
remove_action.triggered.connect(lambda: self.handle_action("Remove")) remove_action.triggered.connect(lambda: self.handle_action("Remove"))
context_menu.addAction(terminal_action) context_menu.addAction(terminal_action)
context_menu.addAction(start_action) context_menu.addAction(start_action)
context_menu.addAction(stop_action) context_menu.addAction(stop_action)
context_menu.addAction(remove_action) context_menu.addAction(remove_action)
@ -290,7 +290,7 @@ class DockerGUI(QMainWindow):
context_menu.addAction(remove_action) context_menu.addAction(remove_action)
context_menu.exec_(current_tab.mapToGlobal(position)) context_menu.exec_(current_tab.mapToGlobal(position))
def setup_auto_refresh(self): def setup_auto_refresh(self):
self.refresh_timer = QTimer(self) self.refresh_timer = QTimer(self)
self.refresh_timer.timeout.connect(self.refresh_data) self.refresh_timer.timeout.connect(self.refresh_data)
@ -331,19 +331,6 @@ class DockerGUI(QMainWindow):
self.refresh_data() self.refresh_data()
self.volumes_tree.clear()
try:
output = subprocess.check_output(["docker", "volume", "ls", "--format", "{{.Name}}\\t{{.Driver}}\\t{{.Mountpoint}}"], stderr=subprocess.STDOUT)
volumes = output.decode().strip().split("\n")
for volume in volumes:
name, driver, mountpoint = volume.split("\t")
item = QTreeWidgetItem([name, driver, mountpoint])
self.volumes_tree.addTopLevelItem(item)
except subprocess.CalledProcessError as e:
print(f"Error refreshing volumes: {e.output.decode()}")
except Exception as e:
print(f"Unexpected error refreshing volumes: {str(e)}")
def refresh_data(self): def refresh_data(self):
self.refresh_containers() self.refresh_containers()
self.refresh_images() self.refresh_images()
@ -424,13 +411,14 @@ class DockerGUI(QMainWindow):
self.volumes_tree.clear() self.volumes_tree.clear()
try: try:
output = subprocess.check_output(["docker", "volume", "ls", "--format", "{{.Name}}\\t{{.Driver}}\\t{{.Mountpoint}}"], stderr=subprocess.STDOUT) output = subprocess.check_output(["docker", "volume", "ls", "--format", "{{.Name}}\\t{{.Driver}}\\t{{.Mountpoint}}"], stderr=subprocess.STDOUT)
volumes = output.decode().strip().split("\n") if output.strip():
for volume in volumes: volumes = output.decode().strip().split("\n")
name, driver, mountpoint = volume.split("\t") for volume in volumes:
item = QTreeWidgetItem([name, driver, mountpoint]) name, driver, mountpoint = volume.split("\t")
self.volumes_tree.addTopLevelItem(item) item = QTreeWidgetItem([name, driver, mountpoint])
self.filter_tree(self.volumes_tree, self.volumes_tab.findChild(QLineEdit).text()) self.volumes_tree.addTopLevelItem(item)
self.restore_selection(self.volumes_tree, selected_items) self.filter_tree(self.volumes_tree, self.volumes_tab.findChild(QLineEdit).text())
self.restore_selection(self.volumes_tree, selected_items)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f"Error refreshing volumes: {e.output.decode()}") print(f"Error refreshing volumes: {e.output.decode()}")
except Exception as e: except Exception as e:
@ -486,7 +474,7 @@ class DockerGUI(QMainWindow):
for item in selected_items: for item in selected_items:
container_id = item.text(0) container_id = item.text(0)
reply = QMessageBox.question(self, "Confirm Removal", reply = QMessageBox.question(self, "Confirm Removal",
f"Are you sure you want to remove container {container_id}?", f"Are you sure you want to remove container {container_id}?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes: if reply == QMessageBox.Yes:
@ -542,7 +530,7 @@ class DockerGUI(QMainWindow):
QMessageBox.critical(self, "Error", f"Failed to create network: {e}") QMessageBox.critical(self, "Error", f"Failed to create network: {e}")
self.refresh_networks() self.refresh_networks()
def remove_network(self): def remove_network(self):
selected_items = self.networks_tree.selectedItems() selected_items = self.networks_tree.selectedItems()
if not selected_items: if not selected_items:
@ -551,7 +539,7 @@ class DockerGUI(QMainWindow):
for item in selected_items: for item in selected_items:
network_name = item.text(1) # Assuming the network name is in the second column network_name = item.text(1) # Assuming the network name is in the second column
reply = QMessageBox.question(self, "Confirm Removal", reply = QMessageBox.question(self, "Confirm Removal",
f"Are you sure you want to remove network {network_name}?", f"Are you sure you want to remove network {network_name}?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes: if reply == QMessageBox.Yes:
@ -584,7 +572,7 @@ class DockerGUI(QMainWindow):
for item in selected_items: for item in selected_items:
volume_name = item.text(0) # Assuming the volume name is in the first column volume_name = item.text(0) # Assuming the volume name is in the first column
reply = QMessageBox.question(self, "Confirm Removal", reply = QMessageBox.question(self, "Confirm Removal",
f"Are you sure you want to remove volume {volume_name}?", f"Are you sure you want to remove volume {volume_name}?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes: if reply == QMessageBox.Yes:
@ -596,7 +584,7 @@ class DockerGUI(QMainWindow):
QMessageBox.critical(self, "Error", f"Failed to remove volume {volume_name}: {e}") QMessageBox.critical(self, "Error", f"Failed to remove volume {volume_name}: {e}")
self.refresh_volumes() self.refresh_volumes()
def open_terminal(self): def open_terminal(self):
selected_items = self.containers_tree.selectedItems() selected_items = self.containers_tree.selectedItems()
if not selected_items: if not selected_items:
@ -604,7 +592,7 @@ class DockerGUI(QMainWindow):
return return
container_id = selected_items[0].text(0) container_id = selected_items[0].text(0)
self.terminal_opener = TerminalOpener(container_id) self.terminal_opener = TerminalOpener(container_id)
self.terminal_opener.error.connect(self.show_terminal_error) self.terminal_opener.error.connect(self.show_terminal_error)
self.terminal_opener.start() self.terminal_opener.start()
@ -616,4 +604,4 @@ if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)
window = DockerGUI() window = DockerGUI()
window.show() window.show()
sys.exit(app.exec_()) sys.exit(app.exec_())