commit d545084d092fa049932e2ec1f9adc92c900eb0e7
Author: Thomas Woerner <twoerner@redhat.com>
Date: Wed Feb 19 13:35:01 2014 +0100
firewall-config: Use left button menu of -applet in Option menu
nm-connection-editor is not used anymore to change zones of connections in the
Option menu "Change Zones of Connections...". The -applet left mouse menu is
attached as a submenu. Zone bindings of connections, interfaces and sources can
now be changes easily.
diff --git a/src/firewall-config b/src/firewall-config
index a00a794..f963cbc 100755
--- a/src/firewall-config
+++ b/src/firewall-config
@@ -58,14 +58,11 @@ if not datadir:
sys.path.insert(0, datadir)
from gtk3_chooserbutton import ChooserButton
-NM_CONNECTION_EDITOR = ""
-for binary in [ "/usr/bin/nm-connection-editor",
- "/bin/nm-connection-editor",
- "/usr/bin/kde-nm-connection-editor",
- "/bin/kde-nm-connection-editor" ]:
- if os.path.exists(binary):
- NM_CONNECTION_EDITOR = binary
- break
+def escape(text):
+ text = text.replace('&', '&')
+ text = text.replace('>', '>')
+ text = text.replace('<', '<')
+ return text
FIREWALL_CONFIG_SCHEMA = "org.fedoraproject.FirewallConfig"
@@ -87,6 +84,10 @@ class FirewallConfig(object):
self.settings = Gio.Settings.new(FIREWALL_CONFIG_SCHEMA)
self.modified_timer = None
+ self.zone_connection_editors = { }
+ self.zone_interface_editors = { }
+ self.zone_source_editors = { }
+
# get icon and logo
(foo, width, height) = Gtk.icon_size_lookup(Gtk.IconSize.BUTTON)
size = min(width, height)
@@ -127,12 +128,13 @@ class FirewallConfig(object):
self.changeZonesConnectionMenuitem = \
builder.get_object("changeZonesConnectionMenuitem")
- if NM_CONNECTION_EDITOR != "":
- self.changeZonesConnectionMenuitem.set_sensitive(True)
- else:
- self.changeZonesConnectionMenuitem.set_tooltip_markup(\
- _("NetworkManager connection editor is missing."))
- self.changeZonesConnectionMenuitem.set_sensitive(False)
+
+ self.left_menu = Gtk.Menu.new()
+ self.left_menu.set_reserve_toggle_size(False)
+ self.changeZonesConnectionMenuitem.set_submenu(self.left_menu)
+ self.changeZonesConnectionMenuitem.connect(
+ "activate", self.left_menu_cb, self.left_menu)
+ self.active_zones = { }
self.panicMenuitem = builder.get_object("panicMenuitem")
self.panic_check_id = \
@@ -963,6 +965,61 @@ class FirewallConfig(object):
except KeyboardInterrupt:
self.onQuit()
+ def left_menu_cb(self, widget, menu):
+ menu.show_all()
+
+ def no_select(self, item):
+ item.deselect()
+
+ def change_zone_interface_editor(self, item, interface, zone):
+ if interface in self.zone_interface_editors:
+ return self.zone_interface_editors[interface].present()
+
+ editor = ZoneInterfaceEditor(self.fw, interface, zone)
+ editor.set_icon(self.icon)
+ editor.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
+ editor.set_transient_for(self.mainWindow)
+ self.zone_interface_editors[interface] = editor
+
+ editor.show_all()
+ result = editor.run()
+ editor.hide()
+ if result == 2:
+ self.fw.changeZoneOfInterface(editor.get_zone(), interface)
+ del self.zone_interface_editors[interface]
+
+ def change_zone_connection_editor(self, item, connection, zone):
+ if connection in self.zone_connection_editors:
+ return self.zone_connection_editors[connection].present()
+
+ editor = ZoneConnectionEditor(self.fw, connection, zone)
+ editor.set_icon(self.icon)
+ editor.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
+ editor.set_transient_for(self.mainWindow)
+ self.zone_connection_editors[connection] = editor
+
+ editor.show_all()
+ editor.run()
+ editor.hide()
+ del self.zone_connection_editors[connection]
+
+ def change_zone_source_editor(self, item, source, zone):
+ if source in self.zone_source_editors:
+ return self.zone_source_editors[source].present()
+
+ editor = ZoneSourceEditor(self.fw, source, zone)
+ editor.set_icon(self.icon)
+ editor.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
+ editor.set_transient_for(self.mainWindow)
+ self.zone_source_editors[source] = editor
+
+ editor.show_all()
+ result = editor.run()
+ editor.hide()
+ if result == 2:
+ self.fw.changeZoneOfSource(editor.get_zone(), source)
+ del self.zone_source_editors[source]
+
def onViewICMPTypes_toggled(self, button):
self.settings.set_boolean("show-icmp-types", button.get_active())
@@ -1013,6 +1070,8 @@ class FirewallConfig(object):
def nm_signal_receiver(self, *args, **kwargs):
#print("nm_signal_receiver", args, kwargs)
+ self.update_active_zones()
+
self.connections.clear()
self.connections_uuid.clear()
@@ -1134,6 +1193,7 @@ class FirewallConfig(object):
self.lockdownLabel.set_text("-")
self.panicLabel.set_text("-")
+ self.update_active_zones()
self.mainToolbar.set_sensitive(self.fw.connected)
self.mainVBox.set_sensitive(self.fw.connected)
self.optionMenuitem.get_submenu().set_sensitive(self.fw.connected)
@@ -1507,6 +1567,7 @@ class FirewallConfig(object):
self.interfaceStore.append([interface, comment])
def interface_added_cb(self, zone, interface):
+ self.update_active_zones()
if not self.runtime_view or zone != self.get_active_zone():
return
iter = self.interfaceStore.get_iter_first()
@@ -1527,8 +1588,10 @@ class FirewallConfig(object):
self.interfaceStore.remove(iter)
break
iter = self.interfaceStore.iter_next(iter)
+ self.update_active_zones()
def zone_of_interface_changed_cb(self, zone, interface):
+ self.update_active_zones()
if not self.runtime_view:
return
iter = self.interfaceStore.get_iter_first()
@@ -1542,6 +1605,7 @@ class FirewallConfig(object):
self._add_interface(interface)
def source_added_cb(self, zone, source):
+ self.update_active_zones()
if not self.runtime_view or zone != self.get_active_zone():
return
iter = self.sourceStore.get_iter_first()
@@ -1554,6 +1618,7 @@ class FirewallConfig(object):
self.sourceStore.append([source])
def source_removed_cb(self, zone, source):
+ self.update_active_zones()
if not self.runtime_view or zone != self.get_active_zone():
return
iter = self.sourceStore.get_iter_first()
@@ -1564,6 +1629,7 @@ class FirewallConfig(object):
iter = self.sourceStore.iter_next(iter)
def zone_of_source_changed_cb(self, zone, source):
+ self.update_active_zones()
if not self.runtime_view:
return
iter = self.sourceStore.get_iter_first()
@@ -1673,18 +1739,119 @@ class FirewallConfig(object):
self.load_direct()
self.load_lockdown_whitelist()
- def nm_connection_editor(self, item, uuid=None):
- if NM_CONNECTION_EDITOR == "":
- self._warning("NetworkManager connection editor is missing.")
+ def update_active_zones(self):
+ self.active_zones.clear()
+
+ # remove all entries for the left menu
+ left_menu_children = self.left_menu.get_children()
+ for child in left_menu_children:
+ self.left_menu.remove(child)
+ child.destroy()
+
+ # add connecitons entry
+ item = Gtk.MenuItem.new()
+ label = Gtk.Label()
+# label.set_markup("<b>"+escape(_("Connections"))+"</b>")
+ label.set_markup(escape(_("Connections")))
+ label.set_alignment(0, 0.5)
+ item.add(label)
+ item.connect("select", self.no_select)
+ self.left_menu.append(item)
+
+ if not self.fw.connected:
return
- if uuid:
- if "kde-" in NM_CONNECTION_EDITOR:
- os.system("%s %s &" % (NM_CONNECTION_EDITOR, uuid))
- else:
- os.system("%s --edit=%s &" % (NM_CONNECTION_EDITOR, uuid))
- else:
- os.system("%s &" % NM_CONNECTION_EDITOR)
+ active_zones = self.fw.getActiveZones()
+ if active_zones:
+ self.active_zones = active_zones
+
+ # get all active connections (NM) and interfaces
+ connections = { }
+ interfaces = { }
+ sources = { }
+ for zone in sorted(self.active_zones):
+ if "interfaces" in self.active_zones[zone]:
+ for interface in sorted(self.active_zones[zone]["interfaces"]):
+ if interface not in self.connections:
+ interfaces[interface] = zone
+ else:
+ # NM controlled
+ connection = self.connections[interface]
+ if connection not in connections:
+ connections[connection] = [ zone, [ interface, ] ]
+ else:
+ connections[connection][1].append(interface)
+ if "sources" in self.active_zones[zone]:
+ for source in sorted(self.active_zones[zone]["sources"]):
+ sources[source] = zone
+
+ # add NM controlled entries
+ for connection in sorted(connections):
+ [ zone, _interfaces ] = connections[connection]
+
+ item = Gtk.MenuItem.new()
+ hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
+ label = Gtk.Label()
+ label.set_markup("%s (%s)\n<small>%s: %s</small>" % \
+ (connection, ",".join(_interfaces), escape(_("Zone")), zone))
+ label.set_alignment(0, 0.5)
+ label.set_padding(12, 0)
+ hbox.pack_start(label, True, True, 0)
+ item.add(hbox)
+ item.connect("activate", self.change_zone_connection_editor, connection, zone)
+ self.left_menu.append(item)
+
+ if len(interfaces) > 0:
+ item = Gtk.MenuItem.new()
+ label = Gtk.Label()
+# label.set_markup("<b>"+escape(_("Interfaces"))+"</b>")
+ label.set_markup(escape(_("Interfaces")))
+ label.set_alignment(0, 0.5)
+ item.add(label)
+ item.connect("select", self.no_select)
+ self.left_menu.append(item)
+
+ # add other interfaces
+ for interface in sorted(interfaces):
+ zone = interfaces[interface]
+
+ item = Gtk.MenuItem.new()
+ hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
+ label = Gtk.Label()
+ label.set_markup("%s\n<small>%s: %s</small>" % \
+ (interface, escape(_("Zone")), zone))
+ label.set_alignment(0, 0.5)
+ label.set_padding(12, 0)
+ hbox.pack_start(label, True, True, 0)
+ item.add(hbox)
+ item.connect("activate", self.change_zone_interface_editor, interface, zone)
+ self.left_menu.append(item)
+
+ if len(sources) > 0:
+ item = Gtk.MenuItem.new()
+ label = Gtk.Label()
+# label.set_markup("<b>"+escape(_("Sources"))+"</b>")
+ label.set_markup(escape(_("Sources")))
+ label.set_alignment(0, 0.5)
+ item.add(label)
+ item.connect("select", self.no_select)
+ self.left_menu.append(item)
+
+ for source in sorted(sources):
+ zone = sources[source]
+
+ item = Gtk.MenuItem.new()
+ hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
+ label = Gtk.Label()
+ label.set_markup("%s\n<small>%s: %s</small>" % \
+ (source, escape(_("Zone")),
+ zone))
+ label.set_alignment(0, 0.5)
+ label.set_padding(12, 0)
+ hbox.pack_start(label, True, True, 0)
+ item.add(hbox)
+ item.connect("activate", self.change_zone_source_editor, source, zone)
+ self.left_menu.append(item)
def onChangeDefaultZone(self, *args):
self.defaultZoneStore.clear()
@@ -5020,6 +5187,7 @@ class ZoneConnectionEditor(Gtk.Dialog):
self.combo = Gtk.ComboBoxText()
zones = self.fw.getZones()
+ self.combo.append_text(_("Default Zone"))
for zone in zones:
self.combo.append_text(zone)
vbox.pack_start(self.combo, True, True, 0)
@@ -5044,7 +5212,10 @@ class ZoneConnectionEditor(Gtk.Dialog):
self.combo_changed(None)
def get_zone(self):
- return self.combo.get_active_text()
+ text = self.combo.get_active_text()
+ if text == _("Default Zone"):
+ text = ""
+ return text
def run(self):
result = super(ZoneConnectionEditor, self).run()
@@ -5068,6 +5239,119 @@ class ZoneConnectionEditor(Gtk.Dialog):
if settings and connection_obj:
settings["connection"]["zone"] = self.get_zone()
connection_obj.Update(settings)
+
+class ZoneInterfaceEditor(Gtk.Dialog):
+ def __init__(self, fw, interface, zone):
+ self.fw = fw
+ self.interface = interface
+ self.zone = zone
+ self.title = _("Select zone for interface '%s'") % self.interface
+
+ super(ZoneInterfaceEditor, self).__init__(self.title)
+
+ self.set_property("width-request", 100)
+ self.resize_to_geometry(100, 50)
+ self.set_resizable(True)
+
+ self.add_button("gtk-close", 1)
+ self.ok_button = self.add_button("gtk-ok", 2)
+ self.ok_button.set_sensitive(False)
+
+ vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
+ vbox.set_border_width(12)
+ vbox.set_homogeneous(False)
+
+ label = Gtk.Label()
+ label.set_text(self.title)
+ label.set_line_wrap(True)
+ label.set_justify(Gtk.Justification.LEFT)
+ label.set_alignment(0, 0.5)
+ vbox.pack_start(label, True, True, 0)
+
+ self.combo = Gtk.ComboBoxText()
+ zones = self.fw.getZones()
+ for zone in zones:
+ self.combo.append_text(zone)
+ vbox.pack_start(self.combo, True, True, 0)
+
+ box = self.get_content_area()
+ box.set_border_width(6)
+ box.set_homogeneous(False)
+ box.pack_start(vbox, False, True, 0)
+
+ combobox_select_text(self.combo, self.zone)
+ self.combo.connect("changed", self.combo_changed)
+
+ def combo_changed(self, combo):
+ self.ok_button.set_sensitive(self.combo.get_active_text() != self.zone)
+
+ def set_zone(self, zone):
+ old_zone = self.zone
+ self.zone = zone
+ if self.combo.get_active_text() == old_zone:
+ combobox_select_text(self.combo, self.zone)
+ else:
+ self.combo_changed(None)
+
+ def get_zone(self):
+ return self.combo.get_active_text()
+
+class ZoneSourceEditor(Gtk.Dialog):
+ def __init__(self, fw, source, zone):
+ self.fw = fw
+ self.source = source
+ self.zone = zone
+ self.title = _("Select zone for source %s") % self.source
+
+ super(ZoneSourceEditor, self).__init__(self.title)
+
+ self.set_property("width-request", 100)
+ self.resize_to_geometry(100, 50)
+ self.set_resizable(True)
+
+ self.add_button("gtk-close", 1)
+ self.ok_button = self.add_button("gtk-ok", 2)
+ self.ok_button.set_sensitive(False)
+
+ vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
+ vbox.set_border_width(12)
+ vbox.set_homogeneous(False)
+
+ label = Gtk.Label()
+ label.set_text(self.title)
+ label.set_line_wrap(True)
+ label.set_justify(Gtk.Justification.LEFT)
+ label.set_alignment(0, 0.5)
+ vbox.pack_start(label, True, True, 0)
+
+ self.combo = Gtk.ComboBoxText()
+ zones = self.fw.getZones()
+ for zone in zones:
+ self.combo.append_text(zone)
+ vbox.pack_start(self.combo, True, True, 0)
+
+ box = self.get_content_area()
+ box.set_border_width(6)
+ box.set_homogeneous(False)
+ box.pack_start(vbox, False, True, 0)
+
+ combobox_select_text(self.combo, self.zone)
+ self.combo.connect("changed", self.combo_changed)
+
+ def combo_changed(self, combo):
+ self.ok_button.set_sensitive(self.combo.get_active_text() != self.zone)
+
+ def set_zone(self, zone):
+ old_zone = self.zone
+ self.zone = zone
+ if self.combo.get_active_text() == old_zone:
+ combobox_select_text(self.combo, self.zone)
+ else:
+ self.combo_changed(None)
+
+ def get_zone(self):
+ return self.combo.get_active_text()
+
# MAIN
if len(sys.argv) > 1:
diff --git a/src/firewall-config.glade b/src/firewall-config.glade
index 2cc33d2..872748e 100755
--- a/src/firewall-config.glade
+++ b/src/firewall-config.glade
@@ -2073,14 +2073,11 @@
</object>
</child>
<child>
- <object class="GtkImageMenuItem" id="changeZonesConnectionMenuitem">
+ <object class="GtkMenuItem" id="changeZonesConnectionMenuitem">
<property name="label" translatable="yes">Change Zones of Connections...</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Change which zone a network connection belongs to.</property>
- <property name="image">image2</property>
- <property name="use_stock">False</property>
- <signal name="activate" handler="nm_connection_editor" swapped="no"/>
</object>
</child>
<child>