diff --git a/blivetgui/actions_menu.py b/blivetgui/actions_menu.py
index 7de14d17..06f46de2 100644
--- a/blivetgui/actions_menu.py
+++ b/blivetgui/actions_menu.py
@@ -42,6 +42,7 @@ def create_menu(self):
items = [("add", self.blivet_gui.add_device),
("delete", self.blivet_gui.delete_selected_partition),
("resize", self.blivet_gui.resize_device),
+ ("rename", self.blivet_gui.rename_device),
("format", self.blivet_gui.format_device),
("label", self.blivet_gui.edit_label),
("unmount", self.blivet_gui.umount_partition),
diff --git a/blivetgui/actions_toolbar.py b/blivetgui/actions_toolbar.py
index 7dd29da9..b1ebdbba 100644
--- a/blivetgui/actions_toolbar.py
+++ b/blivetgui/actions_toolbar.py
@@ -64,6 +64,7 @@ def __init__(self, blivet_gui):
items = [("add", "clicked", self.blivet_gui.add_device),
("delete", "clicked", self.blivet_gui.delete_selected_partition),
("resize", "activate", self.blivet_gui.resize_device),
+ ("rename", "activate", self.blivet_gui.rename_device),
("format", "activate", self.blivet_gui.format_device),
("unmount", "clicked", self.blivet_gui.umount_partition),
("decrypt", "clicked", self.blivet_gui.decrypt_device),
diff --git a/blivetgui/blivet_utils.py b/blivetgui/blivet_utils.py
index 239537af..cb8365e8 100644
--- a/blivetgui/blivet_utils.py
+++ b/blivetgui/blivet_utils.py
@@ -839,6 +839,20 @@ def relabel_format(self, user_input):
return ProxyDataContainer(success=True, actions=[label_ac], message=None,
exception=None, traceback=None)
+ def rename_device(self, user_input):
+ rename_ac = blivet.deviceaction.ActionConfigureDevice(device=user_input.edit_device,
+ attr="name",
+ new_value=user_input.name)
+
+ try:
+ self.storage.devicetree.actions.add(rename_ac)
+ except Exception as e: # pylint: disable=broad-except
+ return ProxyDataContainer(success=False, actions=None, message=None, exception=e,
+ traceback=traceback.format_exc())
+ else:
+ return ProxyDataContainer(success=True, actions=[rename_ac], message=None,
+ exception=None, traceback=None)
+
def edit_lvmvg_device(self, user_input):
""" Edit LVM Volume group
"""
@@ -1410,6 +1424,12 @@ def get_mountpoints(self):
return list(self.storage.mountpoints.keys())
+ def get_names(self):
+ """ Return list of currently used device names
+ """
+
+ return self.storage.names
+
def get_supported_filesystems(self, installer_mode=False):
_fs_types = []
diff --git a/blivetgui/blivetgui.py b/blivetgui/blivetgui.py
index 7d0afd36..45bf3301 100644
--- a/blivetgui/blivetgui.py
+++ b/blivetgui/blivetgui.py
@@ -305,6 +305,30 @@ def resize_device(self, _widget=None):
self._handle_user_change()
self.update_partitions_view()
+ def rename_device(self, _widget=None):
+ device = self.list_partitions.selected_partition[0]
+ names = self.client.remote_call("get_names")
+
+ dialog = edit_dialog.RenameDialog(self.main_window, device, names,
+ installer_mode=self.installer_mode)
+ message = _("Failed to rename the device:")
+ user_input = self.run_dialog(dialog)
+ if user_input.rename:
+ result = self.client.remote_call("rename_device", user_input)
+ if not result.success:
+ if not result.exception:
+ self.show_error_dialog(result.message)
+ else:
+ self._reraise_exception(result.exception, result.traceback, message,
+ dialog_window=dialog.dialog)
+ else:
+ if result.actions:
+ action_str = _("rename {name} {type}").format(name=device.name, type=device.type)
+ self.list_actions.append("edit", action_str, result.actions)
+
+ self._handle_user_change()
+ self.update_partitions_view()
+
def format_device(self, _widget=None):
device = self.list_partitions.selected_partition[0]
diff --git a/blivetgui/dialogs/edit_dialog.py b/blivetgui/dialogs/edit_dialog.py
index c66429b0..dbd0af31 100644
--- a/blivetgui/dialogs/edit_dialog.py
+++ b/blivetgui/dialogs/edit_dialog.py
@@ -28,7 +28,7 @@
from gi.repository import Gtk
from .size_chooser import SizeChooser
-from .helpers import is_mountpoint_valid, is_label_valid
+from .helpers import is_mountpoint_valid, is_label_valid, is_name_valid
from ..dialogs import message_dialogs
from ..gui_utils import locate_ui_file
from ..communication.proxy_utils import ProxyDataContainer
@@ -432,6 +432,87 @@ def _on_format_button(self, _button):
self.dialog.response(Gtk.ResponseType.ACCEPT)
+class RenameDialog(object):
+
+ def __init__(self, main_window, edit_device, names, installer_mode=False):
+ self.main_window = main_window
+ self.edit_device = edit_device
+ self.names = names
+ self.installer_mode = installer_mode
+
+ self.builder = Gtk.Builder()
+ self.builder.set_translation_domain("blivet-gui")
+ self.builder.add_from_file(locate_ui_file("rename_dialog.ui"))
+
+ self.dialog = self.builder.get_object("rename_dialog")
+ self.dialog.set_transient_for(self.main_window)
+
+ self.entry_rename = self.builder.get_object("entry_rename")
+
+ button_cancel = self.builder.get_object("button_cancel")
+ button_cancel.connect("clicked", self._on_cancel_button)
+
+ button_rename = self.builder.get_object("button_rename")
+ button_rename.connect("clicked", self._on_rename_button)
+
+ def set_decorated(self, decorated):
+ self.dialog.set_decorated(decorated)
+
+ # no decoration --> display dialog title in the dialog
+ if not decorated:
+ label = self.builder.get_object("label_title")
+ title = self.dialog.get_title()
+ label.set_text(title)
+
+ def _validate_user_input(self, name):
+ if not is_name_valid(self.edit_device.type, name):
+ msg = _("\"{0}\" is not a valid name.").format(name)
+ message_dialogs.ErrorDialog(self, msg,
+ not self.installer_mode) # do not show decoration in installer mode
+ return False
+
+ if hasattr(self.edit_device, "lvname"):
+ old_name = self.edit_device.lvname
+ new_name = "%s-%s" % (self.edit_device.vg.name, name)
+ else:
+ old_name = self.edit_device.name
+ new_name = name
+
+ if name == old_name:
+ msg = _("Selected device is already named \"{0}\".").format(name)
+ message_dialogs.ErrorDialog(self.dialog, msg,
+ not self.installer_mode) # do not show decoration in installer mode
+ return False
+
+ if new_name in self.names:
+ msg = _("Selected name \"{0}\" is already in use.").format(name)
+ message_dialogs.ErrorDialog(self.dialog, msg,
+ not self.installer_mode) # do not show decoration in installer mode
+ return False
+
+ return True
+
+ def run(self):
+ response = self.dialog.run()
+
+ if response == Gtk.ResponseType.REJECT:
+ self.dialog.destroy()
+ return ProxyDataContainer(edit_device=self.edit_device, rename=False, name=None)
+ else:
+ new_name = self.entry_rename.get_text()
+ if not self._validate_user_input(new_name):
+ return self.run()
+ else:
+ self.dialog.destroy()
+ return ProxyDataContainer(edit_device=self.edit_device, rename=True, name=new_name)
+
+ def _on_cancel_button(self, _button):
+ self.dialog.response(Gtk.ResponseType.REJECT)
+
+ def _on_rename_button(self, _button):
+ self.dialog.response(Gtk.ResponseType.ACCEPT)
+
+
class UnmountDialog(object):
def __init__(self, main_window, edit_device, mountpoints, installer_mode=False):
diff --git a/blivetgui/list_partitions.py b/blivetgui/list_partitions.py
index ace4136b..83c8703d 100644
--- a/blivetgui/list_partitions.py
+++ b/blivetgui/list_partitions.py
@@ -265,6 +265,12 @@ def _allow_relabel_device(self, device):
return device.format.labeling() and device.format.relabels()
+ def _allow_rename_device(self, device):
+ if device.protected or device.format.status:
+ return False
+
+ return hasattr(device, "_renamable") and device._renamable
+
def _allow_add_device(self, device):
if device.protected:
return False
@@ -311,6 +317,9 @@ def activate_action_buttons(self, selected_device):
if self._allow_relabel_device(device):
self.blivet_gui.activate_device_actions(["label"])
+ if self._allow_rename_device(device):
+ self.blivet_gui.activate_device_actions(["rename"])
+
if self._allow_add_device(device):
self.blivet_gui.activate_device_actions(["add"])
diff --git a/data/ui/blivet-gui.ui b/data/ui/blivet-gui.ui
index c3759e5b..5961987e 100644
--- a/data/ui/blivet-gui.ui
+++ b/data/ui/blivet-gui.ui
@@ -43,6 +43,14 @@
True
+
+
+
+
+
+