├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── bug_report.yaml └── workflows │ └── project_automation.yml ├── .gitignore ├── LICENSE ├── NetworkMgr ├── __init__.py ├── configuration.py ├── net_api.py ├── query.py └── trayicon.py ├── README.md ├── compile_translations.sh ├── networkmgr ├── networkmgr_configuration ├── po ├── networkmgr.pot └── pt_Br.po ├── requirements.txt ├── setup.py ├── src ├── auto-switch.py ├── icons │ ├── 128x128 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 16x16 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 192x192 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 20x20 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 24x24 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 256x256 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 32x32 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 36x36 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 48x48 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 512x512 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 64x64 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 72x72 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ ├── 96x96 │ │ └── apps │ │ │ ├── nm-adhoc.png │ │ │ ├── nm-device-wired-secure.png │ │ │ ├── nm-device-wired.png │ │ │ ├── nm-no-connection.png │ │ │ ├── nm-signal-00-secure.png │ │ │ ├── nm-signal-00.png │ │ │ ├── nm-signal-100-secure.png │ │ │ ├── nm-signal-100.png │ │ │ ├── nm-signal-25-secure.png │ │ │ ├── nm-signal-25.png │ │ │ ├── nm-signal-50-secure.png │ │ │ ├── nm-signal-50.png │ │ │ ├── nm-signal-75-secure.png │ │ │ └── nm-signal-75.png │ └── scalable │ │ └── apps │ │ ├── nm-adhoc.svg │ │ ├── nm-device-wired-secure.svg │ │ ├── nm-device-wired.png │ │ ├── nm-no-connection.svg │ │ ├── nm-signal-00-secure.svg │ │ ├── nm-signal-00.svg │ │ ├── nm-signal-100-secure.svg │ │ ├── nm-signal-100.svg │ │ ├── nm-signal-25-secure.svg │ │ ├── nm-signal-25.svg │ │ ├── nm-signal-50-secure.svg │ │ ├── nm-signal-50.svg │ │ ├── nm-signal-75-secure.svg │ │ └── nm-signal-75.svg ├── link-up.py ├── locale │ ├── de │ │ └── networkmgr.po │ ├── nb_NO │ │ └── networkmgr.po │ ├── networkmgr.pot │ ├── ru │ │ └── networkmgr.po │ ├── sv │ │ └── networkmgr.po │ └── zh_CN │ │ └── networkmgr.po ├── networkmgr.conf ├── networkmgr.desktop ├── setup-nic.py └── sudoers.d │ └── networkmgr ├── tests ├── README.md ├── __init__.py └── unit │ └── test_net_api.py └── update_translations.sh /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Each line is a file pattern followed by one or more owners. 2 | 3 | # These owners will be the default owners for everything in 4 | # the repo. Unless a later match takes precedence, 5 | # @global-owner1 and @global-owner2 will be requested for 6 | # review when someone opens a pull request. 7 | # * @global-owner1 @global-owner2 8 | * @ghostbsd/contributors @ghostbsd/new-contributors @ghostbsd/core-contributors @ghostbsd/project-leader -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://www.ghostbsd.org/donate'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report 3 | title: "[Bug]: " 4 | labels: [bug] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this bug report! 10 | For question or comment use [Discussions](https://github.com/ghostbsd/networkmgr/discussions). 11 | - type: dropdown 12 | id: browsers 13 | attributes: 14 | label: Which BSD system 15 | multiple: false 16 | options: 17 | - GhostBSD 18 | - FreeBSD 19 | - DragonFly BSD 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: describe 24 | attributes: 25 | label: Describe the bug 26 | description: A clear and concise description of what the bug is. 27 | placeholder: What happen? 28 | validations: 29 | required: true 30 | - type: textarea 31 | id: reproduce 32 | attributes: 33 | label: How to reproduce the bug? 34 | description: The steps to reproduce the behavior. 35 | placeholder: What are the steps to reproduce the behavior? 36 | validations: 37 | required: true 38 | - type: textarea 39 | id: behavior 40 | attributes: 41 | label: Expected behavior 42 | description: A clear and concise description of what you expected to happen 43 | placeholder: What you expected to happen? 44 | validations: 45 | required: true 46 | -------------------------------------------------------------------------------- /.github/workflows/project_automation.yml: -------------------------------------------------------------------------------- 1 | name: Project automations 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | branches: 8 | - 'master' 9 | 10 | # map fields with customized labels 11 | env: 12 | in_review: In Review 13 | 14 | jobs: 15 | pr_opened: 16 | name: pr_opened 17 | runs-on: ubuntu-latest 18 | if: github.event_name == 'pull_request_target' && github.event.action == 'opened' 19 | steps: 20 | - name: Move PR to ${{ env.in_review }} 21 | uses: leonsteinhaeuser/project-beta-automations@v2.1.0 22 | with: 23 | gh_token: ${{ secrets.MY_GITHUB_TOKEN }} 24 | # user: ghostbsd 25 | organization: ghostbsd 26 | project_id: 4 27 | resource_node_id: ${{ github.event.pull_request.node_id }} 28 | status_value: ${{ env.in_review }} 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | __pycache__ 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Pipenv and lock files 31 | Pipfile 32 | Pipfile.lock 33 | venv/* 34 | venv*/* 35 | 36 | # Pycharm stuff 37 | .idea/* 38 | 39 | # Translations 40 | *.mo 41 | 42 | # Mr Developer 43 | .mr.developer.cfg 44 | .project 45 | .pydevproject 46 | 47 | # Editor Configuration Files 48 | .vscode 49 | 50 | # python core dump 51 | python*.core 52 | 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2023, GhostBSD 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /NetworkMgr/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/NetworkMgr/__init__.py -------------------------------------------------------------------------------- /NetworkMgr/configuration.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import gi 4 | import os 5 | import re 6 | gi.require_version('Gtk', '3.0') 7 | from gi.repository import Gtk, GLib 8 | from NetworkMgr.net_api import ( 9 | defaultcard, 10 | nics_list, 11 | restart_card_network, 12 | restart_routing_and_dhcp, 13 | start_static_network, 14 | wait_inet 15 | ) 16 | from NetworkMgr.query import get_interface_settings 17 | from subprocess import run 18 | 19 | rcconf = open('/etc/rc.conf', 'r').read() 20 | if os.path.exists('/etc/rc.conf.local'): 21 | rcconflocal = open('/etc/rc.conf.local', 'r').read() 22 | else: 23 | rcconflocal = "None" 24 | 25 | 26 | class netCardConfigWindow(Gtk.Window): 27 | 28 | def edit_ipv4_setting(self, widget): 29 | if widget.get_active(): 30 | self.method = widget.get_label() 31 | if self.method == "DHCP": 32 | self.ipInputAddressEntry.set_sensitive(False) 33 | self.ipInputMaskEntry.set_sensitive(False) 34 | self.ipInputGatewayEntry.set_sensitive(False) 35 | self.prymary_dnsEntry.set_sensitive(False) 36 | self.secondary_dnsEntry.set_sensitive(False) 37 | else: 38 | self.ipInputAddressEntry.set_sensitive(True) 39 | self.ipInputMaskEntry.set_sensitive(True) 40 | self.ipInputGatewayEntry.set_sensitive(True) 41 | self.prymary_dnsEntry.set_sensitive(True) 42 | self.secondary_dnsEntry.set_sensitive(True) 43 | if self.method == self.currentSettings["Assignment Method"]: 44 | self.saveButton.set_sensitive(False) 45 | else: 46 | self.saveButton.set_sensitive(True) 47 | 48 | def edit_ipv6_setting(self, widget, value): 49 | if value == "SLAAC": 50 | self.ipInputAddressEntry6.set_sensitive(False) 51 | self.ipInputMaskEntry6.set_sensitive(False) 52 | self.ipInputGatewayEntry6.set_sensitive(False) 53 | self.prymary_dnsEntry6.set_sensitive(False) 54 | self.searchEntry6.set_sensitive(False) 55 | self.saveButton.set_sensitive(False) 56 | else: 57 | self.ipInputAddressEntry6.set_sensitive(True) 58 | self.ipInputMaskEntry6.set_sensitive(True) 59 | self.ipInputGatewayEntry6.set_sensitive(True) 60 | self.prymary_dnsEntry6.set_sensitive(True) 61 | self.searchEntry6.set_sensitive(True) 62 | self.saveButton.set_sensitive(True) 63 | 64 | def entry_trigger_save_button(self, widget, event): 65 | self.saveButton.set_sensitive(True) 66 | 67 | def __init__(self, selected_nic=None): 68 | # Build Default Window 69 | Gtk.Window.__init__(self, title="Network Configuration") 70 | self.set_default_size(475, 400) 71 | self.NICS = nics_list() 72 | DEFAULT_NIC = selected_nic if selected_nic else defaultcard() 73 | # Build Tab 1 Content 74 | # Interface Drop Down Combo Box 75 | cell = Gtk.CellRendererText() 76 | 77 | interfaceComboBox = Gtk.ComboBox() 78 | interfaceComboBox.pack_start(cell, expand=True) 79 | interfaceComboBox.add_attribute(cell, 'text', 0) 80 | 81 | # Add interfaces to a ListStore 82 | store = Gtk.ListStore(str) 83 | 84 | for nic in self.NICS: 85 | store.append([nic]) 86 | 87 | interfaceComboBox.set_model(store) 88 | interfaceComboBox.set_margin_top(15) 89 | interfaceComboBox.set_margin_end(30) 90 | if DEFAULT_NIC: 91 | active_index = self.NICS.index(f"{DEFAULT_NIC}") 92 | interfaceComboBox.set_active(active_index) 93 | self.currentSettings = get_interface_settings(DEFAULT_NIC) 94 | self.method = self.currentSettings["Assignment Method"] 95 | interfaceComboBox.connect("changed", self.cbox_config_refresh, self.NICS) 96 | 97 | # Build Label to sit in front of the ComboBox 98 | labelOne = Gtk.Label(label="Interface:") 99 | labelOne.set_margin_top(15) 100 | labelOne.set_margin_start(30) 101 | 102 | # Add both objects to a single box, which will then be added to the grid 103 | interfaceBox = Gtk.Box(orientation=0, spacing=100) 104 | interfaceBox.pack_start(labelOne, False, False, 0) 105 | interfaceBox.pack_end(interfaceComboBox, True, True, 0) 106 | 107 | # Add radio button to toggle DHCP or not 108 | self.version = self.currentSettings["Assignment Method"] 109 | self.rb_dhcp4 = Gtk.RadioButton.new_with_label(None, "DHCP") 110 | self.rb_dhcp4.set_margin_top(15) 111 | self.rb_manual4 = Gtk.RadioButton.new_with_label_from_widget( 112 | self.rb_dhcp4, "Manual") 113 | self.rb_manual4.set_margin_top(15) 114 | if self.currentSettings["Assignment Method"] == "DHCP": 115 | self.rb_dhcp4.set_active(True) 116 | else: 117 | self.rb_manual4.set_active(True) 118 | self.rb_manual4.join_group(self.rb_dhcp4) 119 | 120 | radioButtonLabel = Gtk.Label(label="IPv4 Method:") 121 | radioButtonLabel.set_margin_top(15) 122 | radioButtonLabel.set_margin_start(30) 123 | 124 | radioBox = Gtk.Box(orientation=0, spacing=50) 125 | radioBox.set_homogeneous(False) 126 | radioBox.pack_start(radioButtonLabel, False, False, 0) 127 | radioBox.pack_start(self.rb_dhcp4, True, False, 0) 128 | radioBox.pack_end(self.rb_manual4, True, True, 0) 129 | 130 | # Add Manual Address Field 131 | ipInputAddressLabel = Gtk.Label(label="Address") 132 | ipInputAddressLabel.set_margin_top(15) 133 | 134 | ipInputMaskLabel = Gtk.Label(label="Subnet Mask") 135 | ipInputMaskLabel.set_margin_top(15) 136 | 137 | ipInputGatewayLabel = Gtk.Label(label="Gateway") 138 | ipInputGatewayLabel.set_margin_top(15) 139 | 140 | self.ipInputAddressEntry = Gtk.Entry() 141 | self.ipInputAddressEntry.set_margin_start(15) 142 | self.ipInputAddressEntry.set_text(self.currentSettings["Interface IP"]) 143 | self.ipInputAddressEntry.connect("key-release-event", self.entry_trigger_save_button) 144 | 145 | self.ipInputMaskEntry = Gtk.Entry() 146 | self.ipInputMaskEntry.set_text(self.currentSettings["Interface Subnet Mask"]) 147 | self.ipInputMaskEntry.connect("key-release-event", self.entry_trigger_save_button) 148 | 149 | self.ipInputGatewayEntry = Gtk.Entry() 150 | self.ipInputGatewayEntry.set_margin_end(15) 151 | self.ipInputGatewayEntry.set_text(self.currentSettings["Default Gateway"]) 152 | self.ipInputGatewayEntry.connect("key-release-event", self.entry_trigger_save_button) 153 | 154 | ipInputBox = Gtk.Box(orientation=0, spacing=0) 155 | ipInputBox.set_homogeneous(True) 156 | ipInputBox.pack_start(ipInputAddressLabel, False, False, 0) 157 | ipInputBox.pack_start(ipInputMaskLabel, False, False, 0) 158 | ipInputBox.pack_start(ipInputGatewayLabel, False, False, 0) 159 | 160 | ipEntryBox = Gtk.Box(orientation=0, spacing=30) 161 | ipEntryBox.pack_start(self.ipInputAddressEntry, False, False, 0) 162 | ipEntryBox.pack_start(self.ipInputMaskEntry, False, False, 0) 163 | ipEntryBox.pack_start(self.ipInputGatewayEntry, False, False, 0) 164 | 165 | # Add DNS Server Settings 166 | prymary_dns_Label = Gtk.Label(label="Primary DNS Servers: ") 167 | prymary_dns_Label.set_margin_top(15) 168 | prymary_dns_Label.set_margin_end(58) 169 | prymary_dns_Label.set_margin_start(30) 170 | 171 | secondary_dns_Label = Gtk.Label(label="Secondary DNS Servers: ") 172 | secondary_dns_Label.set_margin_top(15) 173 | secondary_dns_Label.set_margin_end(58) 174 | secondary_dns_Label.set_margin_start(30) 175 | 176 | self.prymary_dnsEntry = Gtk.Entry() 177 | self.prymary_dnsEntry.set_margin_end(30) 178 | self.prymary_dnsEntry.set_text(self.currentSettings["DNS Server 1"]) 179 | self.prymary_dnsEntry.connect("key-release-event", self.entry_trigger_save_button) 180 | 181 | self.secondary_dnsEntry = Gtk.Entry() 182 | self.secondary_dnsEntry.set_margin_end(30) 183 | self.secondary_dnsEntry.set_text(self.currentSettings["DNS Server 2"]) 184 | self.secondary_dnsEntry.connect("key-release-event", self.entry_trigger_save_button) 185 | 186 | dnsEntryBox1 = Gtk.Box(orientation=0, spacing=0) 187 | dnsEntryBox1.pack_start(prymary_dns_Label, False, False, 0) 188 | 189 | dnsEntryBox1.pack_end(self.prymary_dnsEntry, True, True, 0) 190 | 191 | dnsEntryBox2 = Gtk.Box(orientation=0, spacing=0) 192 | dnsEntryBox2.pack_start(secondary_dns_Label, False, False, 0) 193 | 194 | dnsEntryBox2.pack_end(self.secondary_dnsEntry, True, True, 0) 195 | 196 | # Add Search Domain Settings 197 | searchLabel = Gtk.Label(label="Search domains: ") 198 | searchLabel.set_margin_top(15) 199 | searchLabel.set_margin_end(30) 200 | searchLabel.set_margin_start(30) 201 | 202 | self.searchEntry = Gtk.Entry() 203 | self.searchEntry.set_margin_top(21) 204 | self.searchEntry.set_margin_end(30) 205 | self.searchEntry.set_margin_bottom(30) 206 | self.searchEntry.set_text(self.currentSettings["Search Domain"]) 207 | self.searchEntry.connect("key-release-event", self.entry_trigger_save_button) 208 | 209 | searchBox = Gtk.Box(orientation=0, spacing=0) 210 | searchBox.pack_start(searchLabel, False, False, 0) 211 | searchBox.pack_end(self.searchEntry, True, True, 0) 212 | 213 | self.rb_dhcp4.connect("toggled", self.edit_ipv4_setting) 214 | self.rb_manual4.connect("toggled", self.edit_ipv4_setting) 215 | 216 | if self.currentSettings["Assignment Method"] == "DHCP": 217 | self.ipInputAddressEntry.set_sensitive(False) 218 | self.ipInputMaskEntry.set_sensitive(False) 219 | self.ipInputGatewayEntry.set_sensitive(False) 220 | self.prymary_dnsEntry.set_sensitive(False) 221 | self.secondary_dnsEntry.set_sensitive(False) 222 | self.searchEntry.set_sensitive(False) 223 | 224 | gridOne = Gtk.Grid() 225 | gridOne.set_column_homogeneous(True) 226 | gridOne.set_row_homogeneous(False) 227 | gridOne.set_column_spacing(5) 228 | gridOne.set_row_spacing(10) 229 | gridOne.attach(interfaceBox, 0, 0, 4, 1) 230 | gridOne.attach(radioBox, 0, 1, 4, 1) 231 | gridOne.attach(ipInputBox, 0, 2, 4, 1) 232 | gridOne.attach(ipEntryBox, 0, 3, 4, 1) 233 | gridOne.attach(dnsEntryBox1, 0, 4, 4, 1) 234 | gridOne.attach(dnsEntryBox2, 0, 5, 4, 1) 235 | gridOne.attach(searchBox, 0, 6, 4, 1) 236 | 237 | # Build Tab 2 Content 238 | 239 | # Interface Drop Down Combo Box 240 | cell6 = Gtk.CellRendererText() 241 | 242 | interfaceComboBox6 = Gtk.ComboBox() 243 | interfaceComboBox6.pack_start(cell6, expand=True) 244 | interfaceComboBox6.add_attribute(cell6, 'text', 0) 245 | 246 | # Add interfaces to a ListStore 247 | store6 = Gtk.ListStore(str) 248 | for validinterface6 in self.NICS: 249 | store6.append([validinterface6]) 250 | 251 | interfaceComboBox6.set_model(store) 252 | interfaceComboBox6.set_margin_top(15) 253 | interfaceComboBox6.set_margin_end(30) 254 | 255 | if DEFAULT_NIC: 256 | activeComboBoxObjectIndex6 = self.NICS.index(f"{DEFAULT_NIC}") 257 | interfaceComboBox6.set_active(activeComboBoxObjectIndex6) 258 | interfaceComboBox6.connect("changed", self.cbox_config_refresh) 259 | 260 | # Build Label to sit in front of the ComboBox 261 | labelOne6 = Gtk.Label(label="Interface:") 262 | labelOne6.set_margin_top(15) 263 | labelOne6.set_margin_start(30) 264 | 265 | # Add both objects to a single box, which will then be added to the grid 266 | interfaceBox6 = Gtk.Box(orientation=0, spacing=100) 267 | interfaceBox6.pack_start(labelOne6, False, False, 0) 268 | interfaceBox6.pack_end(interfaceComboBox6, True, True, 0) 269 | 270 | # Add radio button to toggle DHCP or not 271 | rb_slaac6 = Gtk.RadioButton.new_with_label(None, "SLAAC") 272 | rb_slaac6.set_margin_top(15) 273 | rb_slaac6.connect("toggled", self.edit_ipv6_setting, "SLAAC") 274 | rb_manual6 = Gtk.RadioButton.new_with_label_from_widget( 275 | rb_slaac6, "Manual") 276 | rb_manual6.set_margin_top(15) 277 | rb_manual6.join_group(rb_slaac6) 278 | rb_manual6.connect("toggled", self.edit_ipv6_setting, "Manual") 279 | 280 | radioButtonLabel6 = Gtk.Label(label="IPv4 Method:") 281 | radioButtonLabel6.set_margin_top(15) 282 | radioButtonLabel6.set_margin_start(30) 283 | 284 | radioBox6 = Gtk.Box(orientation=0, spacing=50) 285 | radioBox6.set_homogeneous(False) 286 | radioBox6.pack_start(radioButtonLabel6, False, False, 0) 287 | radioBox6.pack_start(rb_slaac6, True, False, 0) 288 | radioBox6.pack_end(rb_manual6, True, True, 0) 289 | 290 | # Add Manual Address Field 291 | ipInputAddressLabel6 = Gtk.Label(label="Address") 292 | ipInputAddressLabel6.set_margin_top(15) 293 | 294 | ipInputMaskLabel6 = Gtk.Label(label="Subnet Mask") 295 | ipInputMaskLabel6.set_margin_top(15) 296 | 297 | ipInputGatewayLabel6 = Gtk.Label(label="Gateway") 298 | ipInputGatewayLabel6.set_margin_top(15) 299 | 300 | self.ipInputAddressEntry6 = Gtk.Entry() 301 | self.ipInputAddressEntry6.set_margin_start(15) 302 | self.ipInputAddressEntry6.connect("key-release-event", self.entry_trigger_save_button) 303 | self.ipInputMaskEntry6 = Gtk.Entry() 304 | self.ipInputAddressEntry6.connect("key-release-event", self.entry_trigger_save_button) 305 | self.ipInputGatewayEntry6 = Gtk.Entry() 306 | self.ipInputGatewayEntry6.set_margin_end(15) 307 | self.ipInputGatewayEntry6.connect("key-release-event", self.entry_trigger_save_button) 308 | 309 | ipInputBox6 = Gtk.Box(orientation=0, spacing=0) 310 | ipInputBox6.set_homogeneous(True) 311 | ipInputBox6.pack_start(ipInputAddressLabel6, False, False, 0) 312 | ipInputBox6.pack_start(ipInputMaskLabel6, False, False, 0) 313 | ipInputBox6.pack_start(ipInputGatewayLabel6, False, False, 0) 314 | 315 | ipEntryBox6 = Gtk.Box(orientation=0, spacing=30) 316 | ipEntryBox6.pack_start(self.ipInputAddressEntry6, False, False, 0) 317 | ipEntryBox6.pack_start(self.ipInputMaskEntry6, False, False, 0) 318 | ipEntryBox6.pack_start(self.ipInputGatewayEntry6, False, False, 0) 319 | 320 | # Add DNS Server Settings 321 | prymary_dns_Label6 = Gtk.Label(label="Primary DNS Servers: ") 322 | prymary_dns_Label6.set_margin_top(15) 323 | prymary_dns_Label6.set_margin_end(58) 324 | prymary_dns_Label6.set_margin_start(30) 325 | 326 | secondary_dns_Label6 = Gtk.Label(label="Secondary DNS Servers: ") 327 | secondary_dns_Label6.set_margin_top(15) 328 | secondary_dns_Label6.set_margin_end(58) 329 | secondary_dns_Label6.set_margin_start(30) 330 | 331 | self.prymary_dnsEntry6 = Gtk.Entry() 332 | self.prymary_dnsEntry6.set_margin_end(30) 333 | self.prymary_dnsEntry6.connect("key-release-event", self.entry_trigger_save_button) 334 | 335 | dnsEntryBox6 = Gtk.Box(orientation=0, spacing=0) 336 | dnsEntryBox6.pack_start(prymary_dns_Label6, False, False, 0) 337 | dnsEntryBox6.pack_end(self.prymary_dnsEntry6, True, True, 0) 338 | 339 | # Add Search Domain Settings 340 | 341 | searchLabel6 = Gtk.Label(label="Search domains: ") 342 | searchLabel6.set_margin_top(15) 343 | searchLabel6.set_margin_end(30) 344 | searchLabel6.set_margin_start(30) 345 | 346 | self.searchEntry6 = Gtk.Entry() 347 | self.searchEntry6.set_margin_top(21) 348 | self.searchEntry6.set_margin_end(30) 349 | self.searchEntry6.set_margin_bottom(30) 350 | self.searchEntry6.connect("key-release-event", self.entry_trigger_save_button) 351 | 352 | searchBox6 = Gtk.Box(orientation=0, spacing=0) 353 | searchBox6.pack_start(searchLabel6, False, False, 0) 354 | searchBox6.pack_end(self.searchEntry6, True, True, 0) 355 | 356 | self.ipInputAddressEntry6.set_sensitive(False) 357 | self.ipInputMaskEntry6.set_sensitive(False) 358 | self.ipInputGatewayEntry6.set_sensitive(False) 359 | self.prymary_dnsEntry6.set_sensitive(False) 360 | self.searchEntry6.set_sensitive(False) 361 | 362 | gridOne6 = Gtk.Grid() 363 | gridOne6.set_column_homogeneous(True) 364 | gridOne6.set_row_homogeneous(False) 365 | gridOne6.set_column_spacing(5) 366 | gridOne6.set_row_spacing(10) 367 | gridOne6.attach(interfaceBox6, 0, 0, 4, 1) 368 | gridOne6.attach(radioBox6, 0, 1, 4, 1) 369 | gridOne6.attach(ipInputBox6, 0, 2, 4, 1) 370 | gridOne6.attach(ipEntryBox6, 0, 3, 4, 1) 371 | gridOne6.attach(dnsEntryBox6, 0, 4, 4, 1) 372 | gridOne6.attach(searchBox6, 0, 5, 4, 1) 373 | gridOne6.set_sensitive(False) 374 | 375 | # Build Notebook 376 | 377 | nb = Gtk.Notebook() 378 | nb.set_margin_start(10) 379 | nb.set_margin_end(10) 380 | nb.set_margin_top(10) 381 | nb.set_margin_bottom(10) 382 | nb.set_tab_pos(2) 383 | # nb.set_sensitive(False) 384 | # Build Save & Cancel Buttons 385 | 386 | self.saveButton = Gtk.Button(label="Save") 387 | self.saveButton.set_margin_bottom(10) 388 | self.saveButton.set_margin_start(10) 389 | self.saveButton.connect("clicked", self.commit_pending_changes) 390 | self.saveButton.set_sensitive(False) 391 | cancelButton = Gtk.Button(label="Cancel") 392 | cancelButton.set_margin_bottom(10) 393 | cancelButton.connect("clicked", self.discard_pending_changes) 394 | buttonsWindow = Gtk.Box(orientation=0, spacing=10) 395 | buttonsWindow.pack_start(self.saveButton, False, False, 0) 396 | buttonsWindow.pack_start(cancelButton, False, False, 0) 397 | 398 | # Apply Tab 1 content and formatting to the notebook 399 | nb.append_page(gridOne) 400 | nb.set_tab_label_text(gridOne, "IPv4 Settings") 401 | 402 | # Apply Tab 2 content and formatting to the notebook 403 | nb.append_page(gridOne6) 404 | nb.set_tab_label_text(gridOne6, "IPv6 Settings WIP") 405 | # Put all the widgets together into one window 406 | mainBox = Gtk.Box(orientation=1, spacing=0) 407 | mainBox.pack_start(nb, True, True, 0) 408 | mainBox.pack_end(buttonsWindow, False, False, 0) 409 | self.add(mainBox) 410 | 411 | # Used with the combo box to refresh the UI of tab 1 with active settings 412 | # for the newly selected active interface. 413 | def cbox_config_refresh(self, widget, nics): 414 | # actions here need to refresh the values on the first two tabs. 415 | self.currentSettings = get_interface_settings(nics[widget.get_active()]) 416 | self.update_interface_settings() 417 | 418 | def update_interface_settings(self): 419 | self.ipInputAddressEntry.set_text(self.currentSettings["Interface IP"]) 420 | self.ipInputMaskEntry.set_text(self.currentSettings["Interface Subnet Mask"]) 421 | self.ipInputGatewayEntry.set_text(self.currentSettings["Default Gateway"]) 422 | self.prymary_dnsEntry.set_text(self.currentSettings["DNS Server 1"]) 423 | self.secondary_dnsEntry.set_text(self.currentSettings["DNS Server 2"]) 424 | self.searchEntry.set_text(self.currentSettings["Search Domain"]) 425 | if self.currentSettings["Assignment Method"] == "DHCP": 426 | self.rb_dhcp4.set_active(True) 427 | else: 428 | self.rb_manual4.set_active(True) 429 | 430 | def commit_pending_changes(self, widget): 431 | self.hide_window() 432 | GLib.idle_add(self.update_system) 433 | 434 | def update_system(self): 435 | nic = self.currentSettings["Active Interface"] 436 | inet = self.ipInputAddressEntry.get_text() 437 | netmask = self.ipInputMaskEntry.get_text() 438 | defaultrouter = self.ipInputGatewayEntry.get_text() 439 | if self.method == 'Manual': 440 | if 'wlan' in nic: 441 | ifconfig_nic = f'ifconfig_{nic}="WPA inet {inet} netmask {netmask}"\n' 442 | else: 443 | ifconfig_nic = f'ifconfig_{nic}="inet {inet} netmask {netmask}"\n' 444 | self.update_rc_conf(ifconfig_nic) 445 | defaultrouter_line = f'defaultrouter="{defaultrouter}"\n' 446 | self.update_rc_conf(defaultrouter_line) 447 | start_static_network(nic, inet, netmask) 448 | resolv_conf = open('/etc/resolv.conf', 'w') 449 | resolv_conf.writelines('# Generated by NetworkMgr\n') 450 | search = self.searchEntry.get_text() 451 | if search: 452 | search_line = f'search {search}\n' 453 | resolv_conf.writelines(search_line) 454 | dns1 = self.prymary_dnsEntry.get_text() 455 | nameserver1_line = f'nameserver {dns1}\n' 456 | resolv_conf.writelines(nameserver1_line) 457 | dns2 = self.secondary_dnsEntry.get_text() 458 | if dns2: 459 | nameserver2_line = f'nameserver {dns2}\n' 460 | resolv_conf.writelines(nameserver2_line) 461 | resolv_conf.close() 462 | else: 463 | if 'wlan' in nic: 464 | ifconfig_nic = f'ifconfig_{nic}="WPA DHCP"\n' 465 | else: 466 | ifconfig_nic = f'ifconfig_{nic}="DHCP"\n' 467 | self.update_rc_conf(ifconfig_nic) 468 | 469 | rc_conf = open('/etc/rc.conf', 'r').read() 470 | for nic_search in self.NICS: 471 | if re.search(f'^ifconfig_{nic_search}=".*inet', rc_conf, re.MULTILINE): 472 | break 473 | else: 474 | defaultrouter_line = f'defaultrouter="{defaultrouter}"\n' 475 | self.remove_rc_conf_line(defaultrouter_line) 476 | restart_card_network(nic) 477 | # sometimes the inet address isn't available immediately after dhcp is enabled. 478 | start_static_network(nic, inet, netmask) 479 | wait_inet(nic) 480 | restart_routing_and_dhcp(nic) 481 | 482 | self.destroy() 483 | 484 | def hide_window(self): 485 | self.hide() 486 | return False 487 | 488 | def discard_pending_changes(self, widget): 489 | self.destroy() 490 | 491 | def update_rc_conf(self, line): 492 | run(f'sysrc {line}', shell=True) 493 | 494 | def remove_rc_conf_line(self, line): 495 | with open('/etc/rc.conf', "r+") as rc_conf: 496 | lines = rc_conf.readlines() 497 | rc_conf.seek(0) 498 | idx = lines.index(line) 499 | lines.pop(idx) 500 | rc_conf.truncate() 501 | rc_conf.writelines(lines) 502 | 503 | 504 | def network_card_configuration(default_int): 505 | win = netCardConfigWindow(default_int) 506 | win.connect("destroy", Gtk.main_quit) 507 | win.show_all() 508 | win.set_keep_above(True) 509 | Gtk.main() 510 | 511 | 512 | def network_card_configuration_window(): 513 | win = netCardConfigWindow() 514 | win.connect("destroy", Gtk.main_quit) 515 | win.show_all() 516 | win.set_keep_above(True) 517 | Gtk.main() 518 | -------------------------------------------------------------------------------- /NetworkMgr/net_api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from subprocess import Popen, PIPE, run, check_output 4 | import re 5 | from time import sleep 6 | 7 | 8 | def card_online(netcard): 9 | lan = Popen('ifconfig ' + netcard, shell=True, stdout=PIPE, 10 | universal_newlines=True) 11 | return 'inet ' in lan.stdout.read() 12 | 13 | 14 | def defaultcard(): 15 | cmd = "netstat -rn | grep default" 16 | nics = Popen(cmd, shell=True, stdout=PIPE, universal_newlines=True) 17 | device = nics.stdout.readlines() 18 | if len(device) == 0: 19 | return None 20 | else: 21 | return list(filter(None, device[0].rstrip().split()))[3] 22 | 23 | 24 | def ifWlanDisable(wificard): 25 | cmd = "ifconfig %s list scan" % wificard 26 | nics = Popen(cmd, shell=True, stdout=PIPE, universal_newlines=True) 27 | return not nics.stdout.read() 28 | 29 | 30 | def ifStatue(wificard): 31 | cmd = "ifconfig %s" % wificard 32 | wl = Popen(cmd, shell=True, stdout=PIPE, universal_newlines=True) 33 | wlout = wl.stdout.read() 34 | return "associated" in wlout 35 | 36 | 37 | def get_ssid(wificard): 38 | wlan = Popen('ifconfig %s | grep ssid' % wificard, 39 | shell=True, stdout=PIPE, universal_newlines=True) 40 | # If there are quotation marks in the string, use that as a separator, 41 | # otherwise use the default whitespace. This is to handle ssid strings 42 | # with spaces in them. These ssid strings will be double-quoted by ifconfig 43 | temp = wlan.stdout.readlines()[0].rstrip() 44 | if '"' in temp: 45 | out = temp.split('"')[1] 46 | else: 47 | out = temp.split()[1] 48 | return out 49 | 50 | 51 | def nics_list(): 52 | not_nics_regex = r"(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|" \ 53 | r"faith|ppp|bridge|wg)[0-9]+(\s*)|vm-[a-z]+(\s*)" 54 | nics = Popen( 55 | 'ifconfig -l', 56 | shell=True, 57 | stdout=PIPE, 58 | universal_newlines=True 59 | ).stdout.read().strip() 60 | return sorted(re.sub(not_nics_regex, '', nics).strip().split()) 61 | 62 | 63 | def ifcardconnected(netcard): 64 | wifi = Popen('ifconfig ' + netcard, shell=True, stdout=PIPE, 65 | universal_newlines=True) 66 | return 'status: active' in wifi.stdout.read() 67 | 68 | 69 | def barpercent(sn): 70 | sig = int(sn.partition(':')[0]) 71 | noise = int(sn.partition(':')[2]) 72 | return int((sig - noise) * 4) 73 | 74 | 75 | def network_service_state(): 76 | return False 77 | 78 | 79 | def networkdictionary(): 80 | nlist = nics_list() 81 | maindictionary = { 82 | 'service': network_service_state(), 83 | 'default': defaultcard() 84 | } 85 | cards = {} 86 | for card in nlist: 87 | if 'wlan' in card: 88 | scanv = f"ifconfig {card} list scan | grep -va BSSID" 89 | wifi = Popen(scanv, shell=True, stdout=PIPE, 90 | universal_newlines=True) 91 | connectioninfo = {} 92 | for line in wifi.stdout: 93 | # don't sort empty ssid 94 | # Window, MacOS and Linux does not show does 95 | if line.startswith(" " * 5): 96 | continue 97 | ssid = line[:33].strip() 98 | info = line[:83][33:].strip().split() 99 | percentage = barpercent(info[3]) 100 | # if ssid exist and percentage is higher keep it 101 | # else add the new one if percentage is higher 102 | if ssid in connectioninfo: 103 | if connectioninfo[ssid][4] > percentage: 104 | continue 105 | info[3] = percentage 106 | info.insert(0, ssid) 107 | # append left over 108 | info.append(line[83:].strip()) 109 | connectioninfo[ssid] = info 110 | if ifWlanDisable(card): 111 | connectionstat = { 112 | "connection": "Disabled", 113 | "ssid": None, 114 | } 115 | elif not ifStatue(card): 116 | connectionstat = { 117 | "connection": "Disconnected", 118 | "ssid": None, 119 | } 120 | else: 121 | ssid = get_ssid(card) 122 | connectionstat = { 123 | "connection": "Connected", 124 | "ssid": ssid, 125 | } 126 | seconddictionary = { 127 | 'state': connectionstat, 128 | 'info': connectioninfo 129 | } 130 | else: 131 | if card_online(card): 132 | connectionstat = {"connection": "Connected"} 133 | elif ifcardconnected(card): 134 | connectionstat = {"connection": "Disconnected"} 135 | else: 136 | connectionstat = {"connection": "Unplug"} 137 | seconddictionary = {'state': connectionstat, 'info': None} 138 | cards[card] = seconddictionary 139 | maindictionary['cards'] = cards 140 | return maindictionary 141 | 142 | 143 | def connectionStatus(card: str, network_info: dict) -> str: 144 | if card is None: 145 | netstate = "Network card is not enabled" 146 | elif 'wlan' in card: 147 | if not ifWlanDisable(card) and ifStatue(card): 148 | cmd1 = "ifconfig %s | grep ssid" % card 149 | cmd2 = "ifconfig %s | grep 'inet '" % card 150 | out1 = Popen(cmd1, shell=True, stdout=PIPE, universal_newlines=True) 151 | out2 = Popen(cmd2, shell=True, stdout=PIPE, universal_newlines=True) 152 | ssid_info = out1.stdout.read().strip() 153 | inet_info = out2.stdout.read().strip() 154 | ssid = network_info['cards'][card]['state']["ssid"] 155 | percentage = network_info['cards'][card]['info'][ssid][4] 156 | netstate = f"Signal Strength: {percentage}% \n{ssid_info} \n{subnetHexToDec(inet_info)}" 157 | else: 158 | netstate = "WiFi %s not connected" % card 159 | else: 160 | cmd = "ifconfig %s | grep 'inet '" % card 161 | out = Popen(cmd, shell=True, stdout=PIPE, universal_newlines=True) 162 | line = out.stdout.read().strip() 163 | netstate = subnetHexToDec(line) 164 | return netstate 165 | 166 | 167 | def switch_default(nic): 168 | nics = nics_list() 169 | nics.remove(nic) 170 | if not nics: 171 | return 172 | for card in nics: 173 | nic_info = Popen( 174 | ['ifconfig', card], 175 | stdout=PIPE, 176 | close_fds=True, 177 | universal_newlines=True 178 | ).stdout.read() 179 | if 'status: active' in nic_info or 'status: associated' in nic_info: 180 | if 'inet ' in nic_info or 'inet6' in nic_info: 181 | run(f'service dhclient restart {card}', shell=True) 182 | break 183 | return 184 | 185 | 186 | def restart_all_nics(widget): 187 | run('service netif restart', shell=True) 188 | 189 | 190 | def stopallnetwork(): 191 | run('service netif stop', shell=True) 192 | 193 | 194 | def startallnetwork(): 195 | run('service netif start', shell=True) 196 | 197 | 198 | def stopnetworkcard(netcard): 199 | run(f'service netif stop {netcard}', shell=True) 200 | switch_default(netcard) 201 | 202 | 203 | def restart_card_network(netcard): 204 | run(f'service netif restart {netcard}', shell=True) 205 | 206 | 207 | def restart_routing_and_dhcp(netcard): 208 | run('service routing restart', shell=True) 209 | sleep(1) 210 | run(f'service dhclient restart {netcard}', shell=True) 211 | 212 | 213 | def start_static_network(netcard, inet, netmask): 214 | run(f'ifconfig {netcard} inet {inet} netmask {netmask}', shell=True) 215 | sleep(1) 216 | run('service routing restart', shell=True) 217 | 218 | 219 | def startnetworkcard(netcard): 220 | run(f'service netif start {netcard}', shell=True) 221 | sleep(1) 222 | run('service routing restart', shell=True) 223 | run(f'service dhclient start {netcard}', shell=True) 224 | 225 | 226 | def wifiDisconnection(wificard): 227 | run(f'ifconfig {wificard} down', shell=True) 228 | run(f"ifconfig {wificard} ssid 'none'", shell=True) 229 | run(f'ifconfig {wificard} up', shell=True) 230 | 231 | 232 | def disableWifi(wificard): 233 | run(f'ifconfig {wificard} down', shell=True) 234 | 235 | 236 | def enableWifi(wificard): 237 | run(f'ifconfig {wificard} up', shell=True) 238 | run(f'ifconfig {wificard} up scan', shell=True) 239 | 240 | 241 | def connectToSsid(name, wificard): 242 | run('killall wpa_supplicant', shell=True) 243 | # service 244 | sleep(0.5) 245 | run(f"ifconfig {wificard} ssid '{name}'", shell=True) 246 | sleep(0.5) 247 | wpa_supplicant = run( 248 | f'wpa_supplicant -B -i {wificard} -c /etc/wpa_supplicant.conf', 249 | shell=True 250 | ) 251 | return wpa_supplicant.returncode == 0 252 | 253 | 254 | def subnetHexToDec(ifconfigstring): 255 | snethex = re.search('0x.{8}', ifconfigstring).group(0)[2:] 256 | snethexlist = re.findall('..', snethex) 257 | snetdec = ".".join(str(int(li, 16)) for li in snethexlist) 258 | outputline = ifconfigstring.replace(re.search('0x.{8}', ifconfigstring).group(0), snetdec) 259 | return outputline 260 | 261 | 262 | def get_ssid_wpa_supplicant_config(ssid): 263 | cmd = f"""grep -A 3 'ssid="{ssid}"' /etc/wpa_supplicant.conf""" 264 | out = Popen(cmd, shell=True, stdout=PIPE, universal_newlines=True) 265 | return out.stdout.read().splitlines() 266 | 267 | 268 | def delete_ssid_wpa_supplicant_config(ssid): 269 | cmd = f"""awk '/sid="{ssid}"/ """ \ 270 | """{print NR-2 "," NR+4 "d"}' """ \ 271 | """/etc/wpa_supplicant.conf | sed -f - /etc/wpa_supplicant.conf""" 272 | out = Popen(cmd, shell=True, stdout=PIPE, universal_newlines=True) 273 | left_over = out.stdout.read() 274 | wpa_supplicant_conf = open('/etc/wpa_supplicant.conf', 'w') 275 | wpa_supplicant_conf.writelines(left_over) 276 | wpa_supplicant_conf.close() 277 | 278 | 279 | def nic_status(card): 280 | out = Popen( 281 | f'ifconfig {card} | grep status:', 282 | shell=True, stdout=PIPE, 283 | universal_newlines=True 284 | ) 285 | return out.stdout.read().split(':')[1].strip() 286 | 287 | 288 | def start_dhcp(wificard): 289 | run(f'dhclient {wificard}', shell=True) 290 | 291 | 292 | def wait_inet(card): 293 | IPREGEX = r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' 294 | status = 'associated' if 'wlan' in card else 'active' 295 | while nic_status(card) != status: 296 | sleep(0.1) 297 | print(nic_status(card)) 298 | while True: 299 | ifcmd = f"ifconfig -f inet:dotted {card}" 300 | ifoutput = check_output(ifcmd.split(" "), universal_newlines=True) 301 | print(ifoutput) 302 | re_ip = re.search(fr'inet {IPREGEX}', ifoutput) 303 | if re_ip and '0.0.0.0' not in re_ip.group(): 304 | print(re_ip) 305 | break 306 | -------------------------------------------------------------------------------- /NetworkMgr/query.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from subprocess import check_output 4 | import re 5 | import os 6 | 7 | 8 | def get_interface_settings(active_nic): 9 | interface_settings = {} 10 | rc_conf = open("/etc/rc.conf", "r").read() 11 | DHCPSearch = re.findall(fr'^ifconfig_{active_nic}=".*DHCP', rc_conf, re.MULTILINE) 12 | print(f"DHCPSearch is {DHCPSearch} and the length is {len(DHCPSearch)}") 13 | if len(DHCPSearch) < 1: 14 | DHCPStatusOutput = "Manual" 15 | else: 16 | DHCPStatusOutput = "DHCP" 17 | 18 | IPREGEX = r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' 19 | 20 | ifcmd = f"ifconfig -f inet:dotted {active_nic}" 21 | ifoutput = check_output(ifcmd.split(" "), universal_newlines=True) 22 | re_ip = re.search(fr'inet {IPREGEX}', ifoutput) 23 | if re_ip: 24 | if_ip = re_ip.group().replace("inet ", "").strip() 25 | re_netmask = re.search(fr'netmask {IPREGEX}', ifoutput) 26 | if_netmask = re_netmask.group().replace("netmask ", "").strip() 27 | re_broadcast = re.search(fr'broadcast {IPREGEX}', ifoutput) 28 | if_broadcast = re_broadcast.group().replace("broadcast ", "").strip() 29 | else: 30 | if_ip = "" 31 | if_netmask = "" 32 | if_broadcast = "" 33 | if (DHCPStatusOutput == "DHCP"): 34 | dhclient_leases = f"/var/db/dhclient.leases.{active_nic}" 35 | 36 | if os.path.exists(dhclient_leases) is False: 37 | print("DHCP is enabled, but we're unable to read the lease " 38 | f"file a /var/db/dhclient.leases.{active_nic}") 39 | gateway = "" 40 | else: 41 | dh_lease = open(dhclient_leases, "r").read() 42 | re_gateway = re.search(fr"option routers {IPREGEX}", dh_lease) 43 | gateway = re_gateway.group().replace("option routers ", "") 44 | else: 45 | rc_conf = open('/etc/rc.conf', 'r').read() 46 | re_gateway = re.search(fr'^defaultrouter="{IPREGEX}"', rc_conf, re.MULTILINE) 47 | if re_gateway: 48 | gateway = re_gateway.group().replace('"', "") 49 | gateway = gateway.replace('defaultrouter=', "") 50 | else: 51 | gateway = "" 52 | 53 | if os.path.exists('/etc/resolv.conf'): 54 | resolv_conf = open('/etc/resolv.conf').read() 55 | nameservers = re.findall(fr'^nameserver {IPREGEX}', str(resolv_conf), re.MULTILINE) 56 | print(nameservers) 57 | 58 | re_domain_search = re.findall('search [a-zA-Z.]*', str(resolv_conf)) 59 | if len(re_domain_search) < 1: 60 | re_domain_search = re.findall('domain (.*)', resolv_conf) 61 | domain_search = str(re_domain_search).replace("domain ", "") 62 | domain_search = domain_search.replace("'", "") 63 | domain_search = domain_search.replace("[", "") 64 | domain_search = domain_search.replace("]", "") 65 | domain_search = domain_search.replace('search', '').strip() 66 | else: 67 | domain_search = '' 68 | nameservers = [] 69 | 70 | interface_settings["Active Interface"] = active_nic 71 | interface_settings["Assignment Method"] = DHCPStatusOutput 72 | interface_settings["Interface IP"] = if_ip 73 | interface_settings["Interface Subnet Mask"] = if_netmask 74 | interface_settings["Broadcast Address"] = if_broadcast 75 | interface_settings["Default Gateway"] = gateway 76 | interface_settings["Search Domain"] = domain_search 77 | 78 | for num in range(len(nameservers)): 79 | interface_settings[ 80 | f"DNS Server {num + 1}" 81 | ] = str(nameservers[(num)]).replace("nameserver", "").strip() 82 | # if DNS Server 1 and 2 are missing create them with empty string 83 | if "DNS Server 1" not in interface_settings: 84 | interface_settings["DNS Server 1"] = "" 85 | if "DNS Server 2" not in interface_settings: 86 | interface_settings["DNS Server 2"] = "" 87 | 88 | return interface_settings 89 | -------------------------------------------------------------------------------- /NetworkMgr/trayicon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import gi 4 | gi.require_version('Gtk', '3.0') 5 | import gettext 6 | import threading 7 | import _thread 8 | import locale 9 | from time import sleep 10 | from gi.repository import Gtk, GObject, GLib 11 | from NetworkMgr.net_api import ( 12 | stopnetworkcard, 13 | startnetworkcard, 14 | wifiDisconnection, 15 | restart_all_nics, 16 | stopallnetwork, 17 | startallnetwork, 18 | connectToSsid, 19 | disableWifi, 20 | enableWifi, 21 | connectionStatus, 22 | networkdictionary, 23 | delete_ssid_wpa_supplicant_config, 24 | nic_status 25 | ) 26 | from NetworkMgr.configuration import network_card_configuration 27 | 28 | 29 | gettext.bindtextdomain('networkmgr', '/usr/local/share/locale') 30 | gettext.textdomain('networkmgr') 31 | _ = gettext.gettext 32 | 33 | encoding = locale.getpreferredencoding() 34 | threadBreak = False 35 | GObject.threads_init() 36 | 37 | 38 | class trayIcon(object): 39 | 40 | def stop_manager(self, widget): 41 | Gtk.main_quit() 42 | 43 | def __init__(self): 44 | self.if_running = False 45 | self.cardinfo = None 46 | self.statusIcon = Gtk.StatusIcon() 47 | self.statusIcon.set_visible(True) 48 | self.statusIcon.connect("activate", self.leftclick) 49 | self.statusIcon.connect('popup-menu', self.icon_clicked) 50 | 51 | def leftclick(self, status_icon): 52 | if not self.thr.is_alive(): 53 | self.thr.start() 54 | button = 1 55 | time = Gtk.get_current_event_time() 56 | position = Gtk.StatusIcon.position_menu 57 | self.nm_menu().popup(None, None, position, status_icon, button, time) 58 | 59 | def icon_clicked(self, status_icon, button, time): 60 | if not self.thr.is_alive(): 61 | self.thr.start() 62 | position = Gtk.StatusIcon.position_menu 63 | self.nm_menu().popup(None, None, position, status_icon, button, time) 64 | 65 | def nm_menu(self): 66 | self.menu = Gtk.Menu() 67 | e_title = Gtk.MenuItem() 68 | e_title.set_label(_("Ethernet Network")) 69 | e_title.set_sensitive(False) 70 | self.menu.append(e_title) 71 | self.menu.append(Gtk.SeparatorMenuItem()) 72 | cardnum = 1 73 | wifinum = 1 74 | cards = self.cardinfo['cards'] 75 | for netcard in cards: 76 | connection_state = cards[netcard]['state']["connection"] 77 | if "wlan" not in netcard: 78 | if connection_state == "Connected": 79 | wired_item = Gtk.MenuItem(_("Wired %s Connected") % cardnum) 80 | wired_item.set_sensitive(False) 81 | self.menu.append(wired_item) 82 | disconnect_item = Gtk.ImageMenuItem(_(f"Disable {netcard}")) 83 | disconnect_item.connect("activate", self.disconnectcard, 84 | netcard) 85 | self.menu.append(disconnect_item) 86 | configure_item = Gtk.ImageMenuItem(f"Configure {netcard}") 87 | configure_item.connect("activate", self.configuration_window_open, netcard) 88 | self.menu.append(configure_item) 89 | elif connection_state == "Disconnected": 90 | notonline = Gtk.MenuItem(_("Wired %s Disconnected") % cardnum) 91 | notonline.set_sensitive(False) 92 | self.menu.append(notonline) 93 | wired_item = Gtk.MenuItem(_("Enable")) 94 | wired_item.connect("activate", self.connectcard, netcard) 95 | self.menu.append(wired_item) 96 | else: 97 | disconnected = Gtk.MenuItem(_("Wired %s Unplug") % cardnum) 98 | disconnected.set_sensitive(False) 99 | self.menu.append(disconnected) 100 | cardnum += 1 101 | self.menu.append(Gtk.SeparatorMenuItem()) 102 | elif "wlan" in netcard: 103 | if connection_state == "Disabled": 104 | wd_title = Gtk.MenuItem() 105 | wd_title.set_label(_("WiFi %s Disabled") % wifinum) 106 | wd_title.set_sensitive(False) 107 | self.menu.append(wd_title) 108 | enawifi = Gtk.MenuItem(_("Enable Wifi %s") % wifinum) 109 | enawifi.connect("activate", self.enable_Wifi, netcard) 110 | self.menu.append(enawifi) 111 | elif connection_state == "Disconnected": 112 | d_title = Gtk.MenuItem() 113 | d_title.set_label(_("WiFi %s Disconnected") % wifinum) 114 | d_title.set_sensitive(False) 115 | self.menu.append(d_title) 116 | self.wifiListMenu(netcard, None, False, cards) 117 | diswifi = Gtk.MenuItem(_("Disable Wifi %s") % wifinum) 118 | diswifi.connect("activate", self.disable_Wifi, netcard) 119 | self.menu.append(diswifi) 120 | else: 121 | ssid = cards[netcard]['state']["ssid"] 122 | bar = cards[netcard]['info'][ssid][4] 123 | wc_title = Gtk.MenuItem(_("WiFi %s Connected") % wifinum) 124 | wc_title.set_sensitive(False) 125 | self.menu.append(wc_title) 126 | connection_item = Gtk.ImageMenuItem(ssid) 127 | connection_item.set_image(self.wifi_signal_icon(bar)) 128 | connection_item.show() 129 | disconnect_item = Gtk.MenuItem(_("Disconnect from %s") % ssid) 130 | disconnect_item.connect("activate", self.disconnect_wifi, 131 | netcard) 132 | self.menu.append(connection_item) 133 | self.menu.append(disconnect_item) 134 | self.wifiListMenu(netcard, ssid, True, cards) 135 | diswifi = Gtk.MenuItem(_("Disable Wifi %s") % wifinum) 136 | diswifi.connect("activate", self.disable_Wifi, netcard) 137 | self.menu.append(diswifi) 138 | configure_item = Gtk.ImageMenuItem(f"Configure {netcard}") 139 | configure_item.connect("activate", self.configuration_window_open, netcard) 140 | self.menu.append(configure_item) 141 | self.menu.append(Gtk.SeparatorMenuItem()) 142 | wifinum += 1 143 | 144 | open_item = Gtk.MenuItem(_("Restart Networking")) 145 | open_item.connect("activate", restart_all_nics) 146 | self.menu.append(open_item) 147 | close_manager = Gtk.MenuItem(_("Close Network Manager")) 148 | close_manager.connect("activate", self.stop_manager) 149 | self.menu.append(close_manager) 150 | self.menu.show_all() 151 | return self.menu 152 | 153 | def ssid_menu_item(self, sn, caps, ssid, ssid_info, wificard): 154 | menu_item = Gtk.ImageMenuItem(ssid) 155 | if caps in ('E', 'ES'): 156 | is_secure = False 157 | click_action = self.menu_click_open 158 | ssid_type = ssid 159 | else: 160 | is_secure = True 161 | click_action = self.menu_click_lock 162 | ssid_type = ssid_info 163 | menu_item.set_image(self.wifi_signal_icon(sn, is_secure)) 164 | menu_item.connect("activate", click_action, ssid_type, wificard) 165 | menu_item.show() 166 | return menu_item 167 | 168 | def wifiListMenu(self, wificard, cssid, passes, cards): 169 | wiconncmenu = Gtk.Menu() 170 | avconnmenu = Gtk.MenuItem(_("Available Connections")) 171 | avconnmenu.set_submenu(wiconncmenu) 172 | for ssid in cards[wificard]['info']: 173 | ssid_info = cards[wificard]['info'][ssid] 174 | ssid = cards[wificard]['info'][ssid][0] 175 | sn = cards[wificard]['info'][ssid][4] 176 | caps = cards[wificard]['info'][ssid][6] 177 | if passes: 178 | if cssid != ssid: 179 | menu_item = self.ssid_menu_item(sn, caps, ssid, ssid_info, wificard) 180 | wiconncmenu.append(menu_item) 181 | else: 182 | menu_item = self.ssid_menu_item(sn, caps, ssid, ssid_info, wificard) 183 | wiconncmenu.append(menu_item) 184 | self.menu.append(avconnmenu) 185 | 186 | def configuration_window_open(self, widget, interface): 187 | network_card_configuration(interface) 188 | 189 | def menu_click_open(self, widget, ssid, wificard): 190 | if f'"{ssid}"' in open("/etc/wpa_supplicant.conf").read(): 191 | connectToSsid(ssid, wificard) 192 | else: 193 | self.Open_Wpa_Supplicant(ssid, wificard) 194 | self.updateinfo() 195 | 196 | def menu_click_lock(self, widget, ssid_info, wificard): 197 | if f'"{ssid_info[0]}"' in open('/etc/wpa_supplicant.conf').read(): 198 | connectToSsid(ssid_info[0], wificard) 199 | else: 200 | self.Authentication(ssid_info, wificard, False) 201 | self.updateinfo() 202 | 203 | def disconnect_wifi(self, widget, wificard): 204 | wifiDisconnection(wificard) 205 | self.updateinfo() 206 | 207 | def disable_Wifi(self, widget, wificard): 208 | disableWifi(wificard) 209 | self.updateinfo() 210 | 211 | def enable_Wifi(self, widget, wificard): 212 | enableWifi(wificard) 213 | self.updateinfo() 214 | 215 | def connectcard(self, widget, netcard): 216 | startnetworkcard(netcard) 217 | self.updateinfo() 218 | 219 | def disconnectcard(self, widget, netcard): 220 | stopnetworkcard(netcard) 221 | self.updateinfo() 222 | 223 | def closeNetwork(self, widget): 224 | stopallnetwork() 225 | self.updateinfo() 226 | 227 | def openNetwork(self, widget): 228 | startallnetwork() 229 | self.updateinfo() 230 | 231 | def signal_icon_name(self, bar, suffix): 232 | if bar > 75: 233 | icon_name = f"nm-signal-100{suffix}" 234 | elif bar > 50: 235 | icon_name = f"nm-signal-75{suffix}" 236 | elif bar > 25: 237 | icon_name = f"nm-signal-50{suffix}" 238 | elif bar > 5: 239 | icon_name = f"nm-signal-25{suffix}" 240 | else: 241 | icon_name = f"nm-signal-00{suffix}" 242 | return icon_name 243 | 244 | def wifi_signal_icon(self, bar, is_secure=False): 245 | img = Gtk.Image() 246 | suffix = "" 247 | if is_secure: 248 | suffix = "-secure" 249 | icon_name = self.signal_icon_name(bar, suffix) 250 | img.set_from_icon_name(icon_name, Gtk.IconSize.MENU) 251 | img.show() 252 | return img 253 | 254 | def updateinfo(self): 255 | if not self.if_running: 256 | self.if_running = True 257 | self.cardinfo = networkdictionary() 258 | defaultcard = self.cardinfo['default'] 259 | default_type = self.network_type(defaultcard) 260 | GLib.idle_add(self.updatetray, defaultcard, default_type) 261 | self.if_running = False 262 | 263 | def updatetray(self, defaultdev, default_type): 264 | self.updatetrayicon(defaultdev, default_type) 265 | self.trayStatus(defaultdev) 266 | 267 | def updatetrayloop(self): 268 | while True: 269 | self.updateinfo() 270 | sleep(20) 271 | 272 | def network_type(self, defaultdev): 273 | if defaultdev is None: 274 | return None 275 | elif 'wlan' in defaultdev: 276 | return 'wifi' 277 | else: 278 | return 'wire' 279 | 280 | def default_wifi_state(self, defaultdev): 281 | info = self.cardinfo['cards'][defaultdev] 282 | if info['state']["connection"] == "Connected": 283 | ssid = info['state']["ssid"] 284 | return info['info'][ssid][4] 285 | else: 286 | return None 287 | 288 | def updatetrayicon(self, defaultdev, card_type): 289 | if card_type is None: 290 | icon_name = 'nm-no-connection' 291 | elif card_type == 'wire': 292 | icon_name = 'nm-device-wired' 293 | else: 294 | wifi_state = self.default_wifi_state(defaultdev) 295 | if wifi_state is None: 296 | icon_name = 'nm-no-connection' 297 | elif wifi_state > 80: 298 | icon_name = 'nm-signal-100' 299 | elif wifi_state > 60: 300 | icon_name = 'nm-signal-75' 301 | elif wifi_state > 40: 302 | icon_name = 'nm-signal-50' 303 | elif wifi_state > 20: 304 | icon_name = 'nm-signal-25' 305 | else: 306 | icon_name = 'nm-signal-00' 307 | self.statusIcon.set_from_icon_name(icon_name) 308 | 309 | def trayStatus(self, defaultdev): 310 | self.statusIcon.set_tooltip_text(connectionStatus(defaultdev, self.cardinfo)) 311 | 312 | def tray(self): 313 | self.if_running = False 314 | self.thr = threading.Thread(target=self.updatetrayloop) 315 | self.thr.setDaemon(True) 316 | self.thr.start() 317 | Gtk.main() 318 | 319 | def close(self, widget): 320 | self.window.hide() 321 | 322 | def add_to_wpa_supplicant(self, widget, ssid_info, card): 323 | pwd = self.password.get_text() 324 | self.setup_wpa_supplicant(ssid_info[0], ssid_info, pwd, card) 325 | _thread.start_new_thread( 326 | self.try_to_connect_to_ssid, 327 | (ssid_info[0], ssid_info, card) 328 | ) 329 | self.window.hide() 330 | 331 | def try_to_connect_to_ssid(self, ssid, ssid_info, card): 332 | if not connectToSsid(ssid, card): 333 | delete_ssid_wpa_supplicant_config(ssid) 334 | GLib.idle_add(self.restart_authentication, ssid_info, card) 335 | else: 336 | for _ in list(range(60)): 337 | if nic_status(card) == 'associated': 338 | self.updateinfo() 339 | break 340 | sleep(1) 341 | else: 342 | delete_ssid_wpa_supplicant_config(ssid) 343 | GLib.idle_add(self.restart_authentication, ssid_info, card) 344 | return 345 | 346 | def restart_authentication(self, ssid_info, card): 347 | self.Authentication(ssid_info, card, True) 348 | 349 | def on_check(self, widget): 350 | self.password.set_visibility(widget.get_active()) 351 | 352 | def Authentication(self, ssid_info, card, failed): 353 | self.window = Gtk.Window() 354 | self.window.set_title(_("Wi-Fi Network Authentication Required")) 355 | self.window.set_border_width(0) 356 | self.window.set_size_request(500, 200) 357 | box1 = Gtk.VBox(False, 0) 358 | self.window.add(box1) 359 | box1.show() 360 | box2 = Gtk.VBox(False, 10) 361 | box2.set_border_width(10) 362 | box1.pack_start(box2, True, True, 0) 363 | box2.show() 364 | # Creating MBR or GPT drive 365 | if failed: 366 | title = _(f"{ssid_info[0]} Wi-Fi Network Authentication failed") 367 | else: 368 | title = _(f"Authentication required by {ssid_info[0]} Wi-Fi Network") 369 | label = Gtk.Label(f"{title}") 370 | label.set_use_markup(True) 371 | pwd_label = Gtk.Label(_("Password:")) 372 | self.password = Gtk.Entry() 373 | self.password.set_visibility(False) 374 | check = Gtk.CheckButton(_("Show password")) 375 | check.connect("toggled", self.on_check) 376 | table = Gtk.Table(1, 2, True) 377 | table.attach(label, 0, 5, 0, 1) 378 | table.attach(pwd_label, 1, 2, 2, 3) 379 | table.attach(self.password, 2, 4, 2, 3) 380 | table.attach(check, 2, 4, 3, 4) 381 | box2.pack_start(table, False, False, 0) 382 | box2 = Gtk.HBox(False, 10) 383 | box2.set_border_width(5) 384 | box1.pack_start(box2, False, True, 0) 385 | box2.show() 386 | # Add create_scheme button 387 | cancel = Gtk.Button(stock=Gtk.STOCK_CANCEL) 388 | cancel.connect("clicked", self.close) 389 | connect = Gtk.Button(stock=Gtk.STOCK_CONNECT) 390 | connect.connect("clicked", self.add_to_wpa_supplicant, ssid_info, card) 391 | table = Gtk.Table(1, 2, True) 392 | table.set_col_spacings(10) 393 | table.attach(connect, 4, 5, 0, 1) 394 | table.attach(cancel, 3, 4, 0, 1) 395 | box2.pack_end(table, True, True, 5) 396 | self.window.show_all() 397 | return 'Done' 398 | 399 | def setup_wpa_supplicant(self, ssid, ssid_info, pwd, card): 400 | if 'RSN' in ssid_info[-1]: 401 | # /etc/wpa_supplicant.conf written by networkmgr 402 | ws = '\nnetwork={' 403 | ws += f'\n ssid="{ssid}"' 404 | ws += '\n key_mgmt=WPA-PSK' 405 | ws += '\n proto=RSN' 406 | ws += f'\n psk="{pwd}"\n' 407 | ws += '}\n' 408 | elif 'WPA' in ssid_info[-1]: 409 | ws = '\nnetwork={' 410 | ws += f'\n ssid="{ssid}"' 411 | ws += '\n key_mgmt=WPA-PSK' 412 | ws += '\n proto=WPA' 413 | ws += f'\n psk="{pwd}"\n' 414 | ws += '}\n' 415 | else: 416 | ws = '\nnetwork={' 417 | ws += f'\n ssid="{ssid}"' 418 | ws += '\n key_mgmt=NONE' 419 | ws += '\n wep_tx_keyidx=0' 420 | ws += f'\n wep_key0={pwd}\n' 421 | ws += '}\n' 422 | wsf = open("/etc/wpa_supplicant.conf", 'a') 423 | wsf.writelines(ws) 424 | wsf.close() 425 | 426 | def Open_Wpa_Supplicant(self, ssid, card): 427 | ws = '\nnetwork={' 428 | ws += f'\n ssid="{ssid}"' 429 | ws += '\n key_mgmt=NONE\n}\n' 430 | wsf = open("/etc/wpa_supplicant.conf", 'a') 431 | wsf.writelines(ws) 432 | wsf.close() 433 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NetworkMgr 2 | 3 | A network manager based on Python and GTK3 for FreeBSD, GhostBSD, and DragonFlyBSD. 4 | 5 | ![alt text](https://image.ibb.co/bWha3R/Screenshot_at_2017_11_24_20_57_33.png) 6 | 7 | NetworkMgr supports FreeBSD rc(8) and openrc(8). 8 | 9 | ## Installation 10 | 11 | ### On FreeBSD 12 | 13 | See https://www.freshports.org/net-mgmt/networkmgr/#add for instructions on installing NetworkMgr. 14 | 15 | #### Install using Python 16 | 17 | Packages that have to be installed before installing NetworkMgr: 18 | 19 | `pkg install sudo py311-setuptools py311-gobject3 gtk-update-icon-cache hicolor-icon-theme` 20 | 21 | If NetworkMgr was previously installed using a package, remove it: 22 | 23 | `pkg delete networkmgr` 24 | 25 | Download NetworkMgr, or clone this repository: 26 | 27 | `git clone https://github.com/GhostBSD/networkmgr.git` 28 | 29 | Then: 30 | 31 | `cd networkmgr` and `python3.8 setup.py install` 32 | 33 | Users of NetworkMgr must be members of the _wheel_ group. To add a user: 34 | 35 | `pw groupmod wheel -m username` 36 | 37 | ## Starting NetworkMgr 38 | 39 | If the desktop environment supports XDG then you can simply log out, or restart the computer. NetworkMgr should start automatically at login time. 40 | 41 | ## Managing Translations 42 | To create a translation file. 43 | ```shell 44 | ./setup.py create_translation --locale=fr 45 | ``` 46 | 47 | ## For Development discussion 48 | 49 | You can join us at [#networkmgr](irc://irc.libera.chat:6697/networkmgr) on irc.libera.chat:6697 50 | -------------------------------------------------------------------------------- /compile_translations.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | msgfmt src/locale/zh_CN/networkmgr.po -o src/locale/zh_CN/networkmgr.mo 4 | msgfmt src/locale/ru/networkmgr.po -o src/locale/ru/networkmgr.mo 5 | -------------------------------------------------------------------------------- /networkmgr: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import signal 4 | from NetworkMgr.trayicon import trayIcon 5 | 6 | signal.signal(signal.SIGINT, signal.SIG_DFL) 7 | 8 | trayIcon().tray() 9 | -------------------------------------------------------------------------------- /networkmgr_configuration: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import signal 4 | from NetworkMgr import configuration 5 | 6 | signal.signal(signal.SIGINT, signal.SIG_DFL) 7 | 8 | configuration.network_card_configuration_window() 9 | -------------------------------------------------------------------------------- /po/networkmgr.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2022-08-29 15:54+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/trayicon.py:67 21 | msgid "Ethernet Network" 22 | msgstr "" 23 | 24 | #: src/trayicon.py:78 25 | #, python-format 26 | msgid "Wired %s Connected" 27 | msgstr "" 28 | 29 | #: src/trayicon.py:81 30 | msgid "Disable" 31 | msgstr "" 32 | 33 | #: src/trayicon.py:86 34 | #, python-format 35 | msgid "Wired %s Disconnected" 36 | msgstr "" 37 | 38 | #: src/trayicon.py:89 39 | msgid "Enable" 40 | msgstr "" 41 | 42 | #: src/trayicon.py:93 43 | #, python-format 44 | msgid "Wired %s Unplug" 45 | msgstr "" 46 | 47 | #: src/trayicon.py:101 48 | #, python-format 49 | msgid "WiFi %s Disabled" 50 | msgstr "" 51 | 52 | #: src/trayicon.py:104 53 | #, python-format 54 | msgid "Enable Wifi %s" 55 | msgstr "" 56 | 57 | #: src/trayicon.py:109 58 | #, python-format 59 | msgid "WiFi %s Disconnected" 60 | msgstr "" 61 | 62 | #: src/trayicon.py:113 src/trayicon.py:131 63 | #, python-format 64 | msgid "Disable Wifi %s" 65 | msgstr "" 66 | 67 | #: src/trayicon.py:119 68 | #, python-format 69 | msgid "WiFi %s Connected" 70 | msgstr "" 71 | 72 | #: src/trayicon.py:125 73 | #, python-format 74 | msgid "Disconnect from %s" 75 | msgstr "" 76 | 77 | #: src/trayicon.py:139 78 | msgid "Enable Networking" 79 | msgstr "" 80 | 81 | #: src/trayicon.py:143 82 | msgid "Disable Networking" 83 | msgstr "" 84 | 85 | #: src/trayicon.py:148 86 | msgid "Close Network Manager" 87 | msgstr "" 88 | 89 | #: src/trayicon.py:156 90 | msgid "Available Connections" 91 | msgstr "" 92 | 93 | #: src/trayicon.py:364 94 | msgid "Wi-Fi Network Authentication Required" 95 | msgstr "" 96 | 97 | #: src/trayicon.py:376 98 | #, python-brace-format 99 | msgid "{ssid_info[0]} Wi-Fi Network Authentication failed" 100 | msgstr "" 101 | 102 | #: src/trayicon.py:378 103 | #, python-brace-format 104 | msgid "Authentication required by {ssid_info[0]} Wi-Fi Network" 105 | msgstr "" 106 | 107 | #: src/trayicon.py:381 108 | msgid "Password:" 109 | msgstr "" 110 | 111 | #: src/trayicon.py:384 112 | msgid "Show password" 113 | msgstr "" 114 | -------------------------------------------------------------------------------- /po/pt_Br.po: -------------------------------------------------------------------------------- 1 | # Portuguese translations for PACKAGE package. 2 | # Copyright (C) 2025 THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Edu_Amr , 2025. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: PACKAGE VERSION\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2022-08-29 15:54+0800\n" 11 | "PO-Revision-Date: 2025-01-05 16:17-0400\n" 12 | "Last-Translator: Edu_Amr \n" 13 | "Language-Team: Portuguese \n" 14 | "Language: pt_Br\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=ASCII\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | 20 | #: src/trayicon.py:67 21 | msgid "Ethernet Network" 22 | msgstr "Rede Ethernet" 23 | 24 | #: src/trayicon.py:78 25 | #, python-format 26 | msgid "Wired %s Connected" 27 | msgstr "Cabo %s Conectado" 28 | 29 | #: src/trayicon.py:81 30 | msgid "Disable" 31 | msgstr "Desativar" 32 | 33 | #: src/trayicon.py:86 34 | #, python-format 35 | msgid "Wired %s Disconnected" 36 | msgstr "Cabo %s Desconectado" 37 | 38 | #: src/trayicon.py:89 39 | msgid "Enable" 40 | msgstr "Ativar" 41 | 42 | #: src/trayicon.py:93 43 | #, python-format 44 | msgid "Wired %s Unplug" 45 | msgstr "Cabo %s Desconectado fisicamente" 46 | 47 | #: src/trayicon.py:101 48 | #, python-format 49 | msgid "WiFi %s Disabled" 50 | msgstr "Wi-Fi %s Desativado" 51 | 52 | #: src/trayicon.py:104 53 | #, python-format 54 | msgid "Enable Wifi %s" 55 | msgstr "Ativar Wi-Fi %s" 56 | 57 | #: src/trayicon.py:109 58 | #, python-format 59 | msgid "WiFi %s Disconnected" 60 | msgstr "Wi-Fi %s Desconectado" 61 | 62 | #: src/trayicon.py:113 src/trayicon.py:131 63 | #, python-format 64 | msgid "Disable Wifi %s" 65 | msgstr "Desativar Wi-Fi %s" 66 | 67 | #: src/trayicon.py:119 68 | #, python-format 69 | msgid "WiFi %s Connected" 70 | msgstr "Wi-Fi %s Conectado" 71 | 72 | #: src/trayicon.py:125 73 | #, python-format 74 | msgid "Disconnect from %s" 75 | msgstr "Desconectar de %s" 76 | 77 | #: src/trayicon.py:139 78 | msgid "Enable Networking" 79 | msgstr "Ativar Rede" 80 | 81 | #: src/trayicon.py:143 82 | msgid "Disable Networking" 83 | msgstr "Desativar Rede" 84 | 85 | #: src/trayicon.py:148 86 | msgid "Close Network Manager" 87 | msgstr "Fechar Gerenciador de Rede" 88 | 89 | #: src/trayicon.py:156 90 | msgid "Available Connections" 91 | msgstr "Conexões Disponíveis" 92 | 93 | #: src/trayicon.py:364 94 | msgid "Wi-Fi Network Authentication Required" 95 | msgstr "Autenticação Necessária para a Rede Wi-Fi" 96 | 97 | #: src/trayicon.py:376 98 | #, python-brace-format 99 | msgid "{ssid_info[0]} Wi-Fi Network Authentication failed" 100 | msgstr "Autenticação falhou na rede Wi-Fi {ssid_info[0]}" 101 | 102 | #: src/trayicon.py:378 103 | #, python-brace-format 104 | msgid "Authentication required by {ssid_info[0]} Wi-Fi Network" 105 | msgstr "Autenticação requerida pela rede Wi-Fi {ssid_info[0]}" 106 | 107 | #: src/trayicon.py:381 108 | msgid "Password:" 109 | msgstr "Senha:" 110 | 111 | #: src/trayicon.py:384 112 | msgid "Show password" 113 | msgstr "Mostrar senha" 114 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | attrs==21.2.0 2 | coverage==6.2 3 | iniconfig==1.1.1 4 | packaging==21.3 5 | pluggy==1.0.0 6 | py==1.11.0 7 | pyparsing==3.0.6 8 | pytest==6.2.5 9 | pytest-cov==3.0.0 10 | Tkinter==0.0.0 11 | toml==0.10.2 12 | tomli==2.0.0 13 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from platform import system 7 | from subprocess import run 8 | 9 | from setuptools import setup, Command, glob 10 | 11 | __VERSION__ = '6.5' 12 | PROGRAM_VERSION = __VERSION__ 13 | 14 | prefix = '/usr/local' if system() == 'FreeBSD' else sys.prefix 15 | 16 | 17 | def datafilelist(installbase, sourcebase): 18 | datafileList = [] 19 | for root, subFolders, files in os.walk(sourcebase): 20 | fileList = [] 21 | for f in files: 22 | fileList.append(os.path.join(root, f)) 23 | datafileList.append((root.replace(sourcebase, installbase), fileList)) 24 | return datafileList 25 | 26 | class UpdateTranslationsCommand(Command): 27 | """Custom command to extract messages and update .po files.""" 28 | 29 | description = 'Extract messages to .pot and update .po' 30 | user_options = [] # No custom options 31 | 32 | def initialize_options(self): 33 | pass 34 | 35 | def finalize_options(self): 36 | pass 37 | 38 | def run(self): 39 | # Define paths 40 | pot_file = 'po/networkmgr.pot' 41 | po_files = glob.glob('po/*.po') 42 | # Step 1: Extract messages to .pot file 43 | print("Extracting messages to .pot file...") 44 | os.system(f'xgettext --from-code=UTF-8 -L Python -o {pot_file} networkmgr/*.py networkmgr') 45 | # Step 2: Update .po files with the new .pot file 46 | print("Updating .po files with new translations...") 47 | for po_file in po_files: 48 | print(f"Updating {po_file}...") 49 | os.system(f'msgmerge -U {po_file} {pot_file}') 50 | print("Translation update complete.") 51 | 52 | class CreateTranslationCommand(Command): 53 | """Custom command to create a new .po file for a specific language.""" 54 | locale = None 55 | description = 'Create a new .po file for the specified language' 56 | user_options = [ 57 | ('locale=', 'l', 'Locale code for the new translation (e.g., fr, es)') 58 | ] 59 | 60 | def initialize_options(self): 61 | self.locale = None # Initialize the locale option to None 62 | 63 | def finalize_options(self): 64 | if self.locale is None: 65 | raise Exception("You must specify the locale code (e.g., --locale=fr)") 66 | 67 | def run(self): 68 | # Define paths 69 | pot_file = 'po/networkmgr.pot' 70 | po_dir = 'po' 71 | po_file = os.path.join(po_dir, f'{self.locale}.po') 72 | # Check if the .pot file exists 73 | if not os.path.exists(pot_file): 74 | print("Extracting messages to .pot file...") 75 | os.system(f'xgettext --from-code=UTF-8 -L Python -o {pot_file} networkmgr/*.py networkmgr') 76 | # Create the new .po file 77 | if not os.path.exists(po_file): 78 | print(f"Creating new {po_file} for locale '{self.locale}'...") 79 | os.makedirs(po_dir, exist_ok=True) 80 | os.system(f'msginit --locale={self.locale} --input={pot_file} --output-file={po_file}') 81 | else: 82 | print(f"PO file for locale '{self.locale}' already exists: {po_file}") 83 | 84 | 85 | networkmgr_share = [ 86 | 'src/auto-switch.py', 87 | 'src/link-up.py', 88 | 'src/setup-nic.py' 89 | ] 90 | 91 | data_files = [ 92 | (f'{prefix}/etc/xdg/autostart', ['src/networkmgr.desktop']), 93 | (f'{prefix}/share/networkmgr', networkmgr_share), 94 | (f'{prefix}/share/locale/zh_CN/LC_MESSAGES', ['src/locale/zh_CN/networkmgr.mo']), 95 | (f'{prefix}/share/locale/ru/LC_MESSAGES', ['src/locale/ru/networkmgr.mo']), 96 | (f'{prefix}/etc/sudoers.d', ['src/sudoers.d/networkmgr']) 97 | ] 98 | 99 | if os.path.exists('/etc/devd'): 100 | data_files.append((f'{prefix}/etc/devd', ['src/networkmgr.conf'])) 101 | if os.path.exists('/etc/devd-openrc'): 102 | data_files.append((f'{prefix}/etc/devd-openrc', ['src/networkmgr.conf'])) 103 | 104 | data_files.extend(datafilelist(f'{prefix}/share/icons/hicolor', 'src/icons')) 105 | 106 | setup( 107 | name="NetworkMgr", 108 | version=PROGRAM_VERSION, 109 | description="NetworkMgr is a tool to manage FreeBSD/GhostBSD network", 110 | license='BSD', 111 | author='Eric Turgeon', 112 | url='https://github/GhostBSD/networkmgr/', 113 | package_dir={'': '.'}, 114 | data_files=data_files, 115 | install_requires=['setuptools'], 116 | packages=['NetworkMgr'], 117 | scripts=['networkmgr', 'networkmgr_configuration'], 118 | cmdclass={ 119 | 'create_translation': CreateTranslationCommand, 120 | 'update_translations': UpdateTranslationsCommand, 121 | } 122 | ) 123 | 124 | run('gtk-update-icon-cache -f /usr/local/share/icons/hicolor', shell=True) 125 | -------------------------------------------------------------------------------- /src/auto-switch.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | """ 3 | auto-switch - is used to automatically switches the default interface go down. 4 | """ 5 | 6 | import sys 7 | import os 8 | import re 9 | from subprocess import Popen, PIPE 10 | 11 | args = sys.argv 12 | if len(args) != 2: 13 | exit() 14 | nic = args[1] 15 | 16 | not_nics_regex = r"(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|wlan" \ 17 | r"ppp|bridge|wg)[0-9]+(\s*)|vm-[a-z]+(\s*)" 18 | 19 | default_nic = Popen( 20 | 'netstat -rn | grep default', 21 | stdout=PIPE, 22 | shell=True, 23 | universal_newlines=True 24 | ).stdout.read() 25 | 26 | nics = Popen( 27 | ['ifconfig', '-l', 'ether'], 28 | stdout=PIPE, 29 | close_fds=True, 30 | universal_newlines=True 31 | ) 32 | 33 | nics_left_over = nics.stdout.read().replace(nic, '').strip() 34 | nic_list = sorted(re.sub(not_nics_regex, '', nics_left_over).strip().split()) 35 | 36 | # Stop the script if the nic is not valid or not in the default route. 37 | if re.search(not_nics_regex, nic): 38 | exit(0) 39 | elif nic not in default_nic: 40 | exit(0) 41 | elif not nic_list: 42 | exit(0) 43 | 44 | nic_ifconfig = Popen( 45 | ['ifconfig', nic], 46 | stdout=PIPE, 47 | close_fds=True, 48 | universal_newlines=True 49 | ).stdout.read() 50 | 51 | dhcp = Popen( 52 | ['sysrc', '-n', f'ifconfig_{nic}'], 53 | stdout=PIPE, 54 | close_fds=True, 55 | universal_newlines=True 56 | ).stdout.read() 57 | 58 | active_status = ( 59 | 'status: active' in nic_ifconfig, 60 | 'status: associated' in nic_ifconfig 61 | ) 62 | 63 | # Stop the interface if it's not active or associated. 64 | # This removes the interface from the default route. 65 | # Restarting routing adds and nic if there is another one that is active 66 | # or associated. 67 | if not any(active_status): 68 | os.system(f'service netif stop {nic}') 69 | if dhcp.strip() == 'DHCP': 70 | for current_nic in nic_list: 71 | output = Popen( 72 | ['ifconfig', current_nic], 73 | stdout=PIPE, 74 | close_fds=True, 75 | universal_newlines=True 76 | ) 77 | nic_ifconfig = output.stdout.read() 78 | status_types = [ 79 | 'active', 80 | 'associated', 81 | ] 82 | found_status = re.search(f"status: ({'|'.join(status_types)})", nic_ifconfig) 83 | found_inet = re.search("inet(\s|6)", nic_ifconfig) 84 | if found_status and found_inet: 85 | os.system(f'service dhclient restart {current_nic}') 86 | break 87 | else: 88 | os.system('service routing restart') 89 | -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/128x128/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/128x128/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/16x16/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/16x16/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/192x192/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/192x192/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/20x20/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/20x20/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/24x24/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/24x24/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/256x256/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/256x256/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/32x32/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/32x32/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/36x36/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/36x36/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/48x48/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/48x48/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/512x512/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/512x512/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/64x64/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/64x64/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/72x72/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/72x72/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-adhoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-adhoc.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-device-wired-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-device-wired-secure.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-device-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-device-wired.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-no-connection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-no-connection.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-00-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-00-secure.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-00.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-100-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-100-secure.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-100.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-25-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-25-secure.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-25.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-50-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-50-secure.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-50.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-75-secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-75-secure.png -------------------------------------------------------------------------------- /src/icons/96x96/apps/nm-signal-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/src/icons/96x96/apps/nm-signal-75.png -------------------------------------------------------------------------------- /src/icons/scalable/apps/nm-device-wired-secure.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 41 | 43 | 47 | 51 | 52 | 54 | 58 | 62 | 63 | 71 | 75 | 79 | 80 | 82 | 86 | 90 | 91 | 94 | 97 | 98 | 105 | 108 | 109 | 117 | 125 | 129 | 133 | 134 | 143 | 152 | 161 | 170 | 179 | 181 | 190 | 191 | 201 | 210 | 219 | 221 | 225 | 229 | 233 | 237 | 238 | 247 | 249 | 253 | 257 | 258 | 266 | 274 | 276 | 280 | 284 | 285 | 293 | 295 | 299 | 303 | 304 | 312 | 320 | 330 | 332 | 336 | 340 | 341 | 351 | 353 | 357 | 361 | 362 | 370 | 372 | 376 | 380 | 381 | 389 | 397 | 405 | 413 | 421 | 429 | 437 | 445 | 453 | 461 | 469 | 477 | 485 | 493 | 501 | 503 | 512 | 513 | 515 | 519 | 523 | 524 | 533 | 535 | 540 | 541 | 544 | 547 | 548 | 549 | 551 | 552 | 554 | image/svg+xml 555 | 557 | 558 | 559 | 560 | 561 | 574 | 588 | 593 | 598 | 604 | 609 | 610 | -------------------------------------------------------------------------------- /src/icons/scalable/apps/nm-no-connection.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 39 | 41 | 43 | 47 | 51 | 52 | 54 | 58 | 62 | 63 | 71 | 75 | 79 | 80 | 82 | 86 | 90 | 91 | 94 | 97 | 98 | 105 | 108 | 109 | 117 | 125 | 129 | 133 | 134 | 143 | 152 | 161 | 170 | 179 | 181 | 190 | 191 | 201 | 210 | 219 | 221 | 225 | 229 | 233 | 237 | 238 | 247 | 249 | 253 | 257 | 258 | 266 | 274 | 276 | 280 | 284 | 285 | 293 | 295 | 299 | 303 | 304 | 312 | 320 | 330 | 332 | 336 | 340 | 341 | 351 | 353 | 357 | 361 | 362 | 370 | 372 | 376 | 380 | 381 | 389 | 397 | 405 | 413 | 421 | 429 | 437 | 445 | 453 | 461 | 469 | 477 | 485 | 493 | 501 | 503 | 512 | 513 | 515 | 520 | 521 | 524 | 527 | 528 | 530 | 534 | 538 | 539 | 548 | 558 | 561 | 565 | 566 | 567 | 569 | 570 | 572 | image/svg+xml 573 | 575 | 576 | 577 | 578 | 579 | 592 | 606 | 611 | 616 | 621 | 628 | 633 | 634 | -------------------------------------------------------------------------------- /src/link-up.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | import os 4 | import re 5 | import sys 6 | from subprocess import Popen, PIPE, run 7 | 8 | args = sys.argv 9 | if len(args) != 2: 10 | exit(1) 11 | nic = args[1] 12 | 13 | not_nics_regex = "(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|" \ 14 | "ppp|bridge|wg|wlan)[0-9]+|vm-[a-z]+" 15 | 16 | # Stop the script if the nic is not valid. 17 | if re.search(not_nics_regex, nic): 18 | exit(0) 19 | 20 | dhcp = Popen( 21 | ['sysrc', '-n', f'ifconfig_{nic}'], 22 | stdout=PIPE, 23 | close_fds=True, 24 | universal_newlines=True 25 | ).stdout.read() 26 | 27 | if os.path.exists(f'/tmp/network-{nic}'): 28 | network = open(f'/tmp/network-{nic}', 'r').read() 29 | if 'attached' in network: 30 | if dhcp.strip() == 'DHCP': 31 | Popen(f'service dhclient quietstart {nic}', shell=True) 32 | else: 33 | Popen(f'service routing restart', shell=True) 34 | with open(f'/tmp/network-{nic}', 'w') as network: 35 | network.writelines(f'linked') 36 | exit(0) 37 | 38 | nic_ifconfig = Popen( 39 | ['ifconfig', nic], 40 | stdout=PIPE, 41 | close_fds=True, 42 | universal_newlines=True 43 | ).stdout.read() 44 | 45 | if 'inet ' in nic_ifconfig: 46 | Popen( 47 | f'service routing restart ; ' 48 | f'service dhclient restart {nic}', 49 | shell=True 50 | ) 51 | else: 52 | Popen( 53 | f'service netif start {nic} ; ' 54 | 'sleep 1 ; ' 55 | f'service routing restart ; ' 56 | f'service dhclient restart {nic}', 57 | shell=True 58 | ) 59 | -------------------------------------------------------------------------------- /src/locale/de/networkmgr.po: -------------------------------------------------------------------------------- 1 | # Language locale/de_DE translations for NetworkMgr package. 2 | # Copyright (C) 2023 THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Joshua Hoffmann , 2023. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2023-12-14 17:25+0000\n" 12 | "PO-Revision-Date: 2023-12-14 17:25+0000\n" 13 | "Last-Translator: Joshua Hoffmann \n" 14 | "Language-Team: Language locale/de\n" 15 | "Language: locale/de/LC_MESSAGES/networkmgr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/trayicon.py:67 21 | msgid "Ethernet Network" 22 | msgstr "Ethernet-Netzwerk" 23 | 24 | #: src/trayicon.py:78 25 | #, python-format 26 | msgid "Wired %s Connected" 27 | msgstr "Kabel an %s angeschlossen" 28 | 29 | #: src/trayicon.py:81 30 | msgid "Disable" 31 | msgstr "Deaktivieren" 32 | 33 | #: src/trayicon.py:86 34 | #, python-format 35 | msgid "Wired %s Disconnected" 36 | msgstr "Kabel von %s getrennt" 37 | 38 | #: src/trayicon.py:89 39 | msgid "Enable" 40 | msgstr "Aktivieren" 41 | 42 | #: src/trayicon.py:93 43 | #, python-format 44 | msgid "Wired %s Unplug" 45 | msgstr "Kabel von %s abgesteckt" 46 | 47 | #: src/trayicon.py:101 48 | #, python-format 49 | msgid "WiFi %s Disabled" 50 | msgstr "WLAN %s deaktiviert" 51 | 52 | #: src/trayicon.py:104 53 | #, python-format 54 | msgid "Enable Wifi %s" 55 | msgstr "WLAN %s aktivieren" 56 | 57 | #: src/trayicon.py:109 58 | #, python-format 59 | msgid "WiFi %s Disconnected" 60 | msgstr "WLAN %s getrennt" 61 | 62 | #: src/trayicon.py:113 src/trayicon.py:131 63 | #, python-format 64 | msgid "Disable Wifi %s" 65 | msgstr "WLAN %s deaktivieren" 66 | 67 | #: src/trayicon.py:119 68 | #, python-format 69 | msgid "WiFi %s Connected" 70 | msgstr "WLAN %s verbunden" 71 | 72 | #: src/trayicon.py:125 73 | #, python-format 74 | msgid "Disconnect from %s" 75 | msgstr "%s trennen" 76 | 77 | #: src/trayicon.py:139 78 | msgid "Enable Networking" 79 | msgstr "Netzwerk aktivieren" 80 | 81 | #: src/trayicon.py:143 82 | msgid "Disable Networking" 83 | msgstr "Netzwerkverbindungen deaktivieren" 84 | 85 | #: src/trayicon.py:148 86 | msgid "Close Network Manager" 87 | msgstr "Network Manager schließen" 88 | 89 | #: src/trayicon.py:156 90 | msgid "Available Connections" 91 | msgstr "Verfügbare Verbindungen" 92 | 93 | #: src/trayicon.py:364 94 | msgid "Wi-Fi Network Authentication Required" 95 | msgstr "WLAN erfordert Legitimierung" 96 | 97 | #: src/trayicon.py:376 98 | #, python-brace-format 99 | msgid "{ssid_info[0]} Wi-Fi Network Authentication failed" 100 | msgstr "Legitimierung für WLAN {ssid_info[0]} fehlgeschlagen" 101 | 102 | #: src/trayicon.py:378 103 | #, python-brace-format 104 | msgid "Authentication required by {ssid_info[0]} Wi-Fi Network" 105 | msgstr "Legitimierung für WLAN {ssid_info[0]} erforderlich" 106 | 107 | #: src/trayicon.py:381 108 | msgid "Password:" 109 | msgstr "Passwort:" 110 | 111 | #: src/trayicon.py:384 112 | msgid "Show password" 113 | msgstr "Passwort anzeigen" 114 | -------------------------------------------------------------------------------- /src/locale/nb_NO/networkmgr.po: -------------------------------------------------------------------------------- 1 | # Language locale/nb_NO translations for NetworkMgr package. 2 | # Copyright (C) 2023 THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Joshua Hoffmann , 2023. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2023-12-14 17:25+0000\n" 12 | "PO-Revision-Date: 2023-12-14 17:25+0000\n" 13 | "Last-Translator: Joshua Hoffmann \n" 14 | "Language-Team: Language locale/nb_NO\n" 15 | "Language: locale/nb_NO/LC_MESSAGES/networkmgr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/trayicon.py:67 21 | msgid "Ethernet Network" 22 | msgstr "Ethernet-nettverk" 23 | 24 | #: src/trayicon.py:78 25 | #, python-format 26 | msgid "Wired %s Connected" 27 | msgstr "Kablet %s er tilkoblet" 28 | 29 | #: src/trayicon.py:81 30 | msgid "Disable" 31 | msgstr "Deaktiver" 32 | 33 | #: src/trayicon.py:86 34 | #, python-format 35 | msgid "Wired %s Disconnected" 36 | msgstr "Kablet forbindelse %s er frakoblet" 37 | 38 | #: src/trayicon.py:89 39 | msgid "Enable" 40 | msgstr "Aktiver" 41 | 42 | #: src/trayicon.py:93 43 | #, python-format 44 | msgid "Wired %s Unplug" 45 | msgstr "Kablet forbindelse %s er frakoblet" 46 | 47 | #: src/trayicon.py:101 48 | #, python-format 49 | msgid "WiFi %s Disabled" 50 | msgstr "WiFi %s deaktivert" 51 | 52 | #: src/trayicon.py:104 53 | #, python-format 54 | msgid "Enable Wifi %s" 55 | msgstr "Aktiver WiFi %s" 56 | 57 | #: src/trayicon.py:109 58 | #, python-format 59 | msgid "WiFi %s Disconnected" 60 | msgstr "WiFi %s frakoblet" 61 | 62 | #: src/trayicon.py:113 src/trayicon.py:131 63 | #, python-format 64 | msgid "Disable Wifi %s" 65 | msgstr "Deaktiver WiFi %s" 66 | 67 | #: src/trayicon.py:119 68 | #, python-format 69 | msgid "WiFi %s Connected" 70 | msgstr "WiFi %s tillkoblet" 71 | 72 | #: src/trayicon.py:125 73 | #, python-format 74 | msgid "Disconnect from %s" 75 | msgstr "Koble fra %s" 76 | 77 | #: src/trayicon.py:139 78 | msgid "Enable Networking" 79 | msgstr "Aktiver nettverksfunksjon" 80 | 81 | #: src/trayicon.py:143 82 | msgid "Disable Networking" 83 | msgstr "Deaktiver nettverkstilkoblinger" 84 | 85 | #: src/trayicon.py:148 86 | msgid "Close Network Manager" 87 | msgstr "Lukk Network Manager" 88 | 89 | #: src/trayicon.py:156 90 | msgid "Available Connections" 91 | msgstr "Tilgjengelige forbindelser" 92 | 93 | #: src/trayicon.py:364 94 | msgid "Wi-Fi Network Authentication Required" 95 | msgstr "Wi-Fi-nettverksautentisering kreves" 96 | 97 | #: src/trayicon.py:376 98 | #, python-brace-format 99 | msgid "{ssid_info[0]} Wi-Fi Network Authentication failed" 100 | msgstr "{ssid_info[0]} Wi-Fi-nettverksautentisering mislyktes" 101 | 102 | #: src/trayicon.py:378 103 | #, python-brace-format 104 | msgid "Authentication required by {ssid_info[0]} Wi-Fi Network" 105 | msgstr "Autentisering kreves av {ssid_info[0]} Wi-Fi-nettverk" 106 | 107 | #: src/trayicon.py:381 108 | msgid "Password:" 109 | msgstr "Passord:" 110 | 111 | #: src/trayicon.py:384 112 | msgid "Show password" 113 | msgstr "Vis passord" 114 | -------------------------------------------------------------------------------- /src/locale/networkmgr.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2022-08-29 15:54+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/trayicon.py:67 21 | msgid "Ethernet Network" 22 | msgstr "" 23 | 24 | #: src/trayicon.py:78 25 | #, python-format 26 | msgid "Wired %s Connected" 27 | msgstr "" 28 | 29 | #: src/trayicon.py:81 30 | msgid "Disable" 31 | msgstr "" 32 | 33 | #: src/trayicon.py:86 34 | #, python-format 35 | msgid "Wired %s Disconnected" 36 | msgstr "" 37 | 38 | #: src/trayicon.py:89 39 | msgid "Enable" 40 | msgstr "" 41 | 42 | #: src/trayicon.py:93 43 | #, python-format 44 | msgid "Wired %s Unplug" 45 | msgstr "" 46 | 47 | #: src/trayicon.py:101 48 | #, python-format 49 | msgid "WiFi %s Disabled" 50 | msgstr "" 51 | 52 | #: src/trayicon.py:104 53 | #, python-format 54 | msgid "Enable Wifi %s" 55 | msgstr "" 56 | 57 | #: src/trayicon.py:109 58 | #, python-format 59 | msgid "WiFi %s Disconnected" 60 | msgstr "" 61 | 62 | #: src/trayicon.py:113 src/trayicon.py:131 63 | #, python-format 64 | msgid "Disable Wifi %s" 65 | msgstr "" 66 | 67 | #: src/trayicon.py:119 68 | #, python-format 69 | msgid "WiFi %s Connected" 70 | msgstr "" 71 | 72 | #: src/trayicon.py:125 73 | #, python-format 74 | msgid "Disconnect from %s" 75 | msgstr "" 76 | 77 | #: src/trayicon.py:139 78 | msgid "Enable Networking" 79 | msgstr "" 80 | 81 | #: src/trayicon.py:143 82 | msgid "Disable Networking" 83 | msgstr "" 84 | 85 | #: src/trayicon.py:148 86 | msgid "Close Network Manager" 87 | msgstr "" 88 | 89 | #: src/trayicon.py:156 90 | msgid "Available Connections" 91 | msgstr "" 92 | 93 | #: src/trayicon.py:364 94 | msgid "Wi-Fi Network Authentication Required" 95 | msgstr "" 96 | 97 | #: src/trayicon.py:376 98 | #, python-brace-format 99 | msgid "{ssid_info[0]} Wi-Fi Network Authentication failed" 100 | msgstr "" 101 | 102 | #: src/trayicon.py:378 103 | #, python-brace-format 104 | msgid "Authentication required by {ssid_info[0]} Wi-Fi Network" 105 | msgstr "" 106 | 107 | #: src/trayicon.py:381 108 | msgid "Password:" 109 | msgstr "" 110 | 111 | #: src/trayicon.py:384 112 | msgid "Show password" 113 | msgstr "" 114 | -------------------------------------------------------------------------------- /src/locale/ru/networkmgr.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2022-08-29 15:54+0800\n" 12 | "PO-Revision-Date: 2022-08-30 00:05+0300\n" 13 | "Last-Translator: Alexander Alexeev \n" 14 | "Language-Team: Language locale/ru\n" 15 | "Language: locale/ru/LC_MESSAGES/networkmgr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/trayicon.py:67 21 | msgid "Ethernet Network" 22 | msgstr "Сеть Ethernet" 23 | 24 | #: src/trayicon.py:78 25 | #, python-format 26 | msgid "Wired %s Connected" 27 | msgstr "Проводное соединение %s подключено" 28 | 29 | #: src/trayicon.py:81 30 | msgid "Disable" 31 | msgstr "Отключить" 32 | 33 | #: src/trayicon.py:86 34 | #, python-format 35 | msgid "Wired %s Disconnected" 36 | msgstr "Проводное соединение %s отключено" 37 | 38 | #: src/trayicon.py:89 39 | msgid "Enable" 40 | msgstr "Включить" 41 | 42 | #: src/trayicon.py:93 43 | #, python-format 44 | msgid "Wired %s Unplug" 45 | msgstr "Проводное соединение %s разорвано" 46 | 47 | #: src/trayicon.py:101 48 | #, python-format 49 | msgid "WiFi %s Disabled" 50 | msgstr "Соединение по WiFi %s отключено" 51 | 52 | #: src/trayicon.py:104 53 | #, python-format 54 | msgid "Enable Wifi %s" 55 | msgstr "Включить соединение по WiFi %s" 56 | 57 | #: src/trayicon.py:109 58 | #, python-format 59 | msgid "WiFi %s Disconnected" 60 | msgstr "Подключение по WiFi %s разорвано" 61 | 62 | #: src/trayicon.py:113 src/trayicon.py:131 63 | #, python-format 64 | msgid "Disable Wifi %s" 65 | msgstr "Отключить соединение по WiFi %s" 66 | 67 | #: src/trayicon.py:119 68 | #, python-format 69 | msgid "WiFi %s Connected" 70 | msgstr "Подключение по WiFi %s установлено" 71 | 72 | #: src/trayicon.py:125 73 | #, python-format 74 | msgid "Disconnect from %s" 75 | msgstr "Отключиться от %s" 76 | 77 | #: src/trayicon.py:139 78 | msgid "Enable Networking" 79 | msgstr "Включить сеть" 80 | 81 | #: src/trayicon.py:143 82 | msgid "Disable Networking" 83 | msgstr "Отключить сеть" 84 | 85 | #: src/trayicon.py:148 86 | msgid "Close Network Manager" 87 | msgstr "Закрыть Network Manager" 88 | 89 | #: src/trayicon.py:156 90 | msgid "Available Connections" 91 | msgstr "Доступные подключения" 92 | 93 | #: src/trayicon.py:364 94 | msgid "Wi-Fi Network Authentication Required" 95 | msgstr "Требуется региcтрация в сети WiFi" 96 | 97 | #: src/trayicon.py:376 98 | #, python-brace-format 99 | msgid "{ssid_info[0]} Wi-Fi Network Authentication failed" 100 | msgstr "Ошибка при регистрации в сети WiFi {ssid_info[0]}" 101 | 102 | #: src/trayicon.py:378 103 | #, python-brace-format 104 | msgid "Authentication required by {ssid_info[0]} Wi-Fi Network" 105 | msgstr "Требуется региcтрация в сети WiFi {ssid_info[0]}" 106 | 107 | #: src/trayicon.py:381 108 | msgid "Password:" 109 | msgstr "Пароль:" 110 | 111 | #: src/trayicon.py:384 112 | msgid "Show password" 113 | msgstr "Показать пароль" 114 | -------------------------------------------------------------------------------- /src/locale/sv/networkmgr.po: -------------------------------------------------------------------------------- 1 | # Language locale/sv_SE translations for NetworkMgr package. 2 | # Copyright (C) 2023 THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Joshua Hoffmann , 2023. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2023-12-14 17:25+0000\n" 12 | "PO-Revision-Date: 2023-12-14 17:25+0000\n" 13 | "Last-Translator: Joshua Hoffmann \n" 14 | "Language-Team: Language locale/sv\n" 15 | "Language: locale/sv/LC_MESSAGES/networkmgr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/trayicon.py:67 21 | msgid "Ethernet Network" 22 | msgstr "Ethernet-nätverk" 23 | 24 | #: src/trayicon.py:78 25 | #, python-format 26 | msgid "Wired %s Connected" 27 | msgstr "trådbunden anslutning %s ansluten" 28 | 29 | #: src/trayicon.py:81 30 | msgid "Disable" 31 | msgstr "Inaktivera" 32 | 33 | #: src/trayicon.py:86 34 | #, python-format 35 | msgid "Wired %s Disconnected" 36 | msgstr "Kabel frånkopplad från %s" 37 | 38 | #: src/trayicon.py:89 39 | msgid "Enable" 40 | msgstr "Aktivera" 41 | 42 | #: src/trayicon.py:93 43 | #, python-format 44 | msgid "Wired %s Unplug" 45 | msgstr "Kabel borttagen från %s" 46 | 47 | #: src/trayicon.py:101 48 | #, python-format 49 | msgid "WiFi %s Disabled" 50 | msgstr "WiFi %s inaktiverat" 51 | 52 | #: src/trayicon.py:104 53 | #, python-format 54 | msgid "Enable Wifi %s" 55 | msgstr "Aktivera WiFi %s" 56 | 57 | #: src/trayicon.py:109 58 | #, python-format 59 | msgid "WiFi %s Disconnected" 60 | msgstr "WiFi %s har kopplats bort" 61 | 62 | #: src/trayicon.py:113 src/trayicon.py:131 63 | #, python-format 64 | msgid "Disable Wifi %s" 65 | msgstr "Inaktivera WiFi %s" 66 | 67 | #: src/trayicon.py:119 68 | #, python-format 69 | msgid "WiFi %s Connected" 70 | msgstr "WiFi %s ansluten" 71 | 72 | #: src/trayicon.py:125 73 | #, python-format 74 | msgid "Disconnect from %s" 75 | msgstr "Koppla bort %s" 76 | 77 | #: src/trayicon.py:139 78 | msgid "Enable Networking" 79 | msgstr "Aktivera nätverk" 80 | 81 | #: src/trayicon.py:143 82 | msgid "Disable Networking" 83 | msgstr "Avaktivera nätverksanslutningar" 84 | 85 | #: src/trayicon.py:148 86 | msgid "Close Network Manager" 87 | msgstr "Stäng Network Manager" 88 | 89 | #: src/trayicon.py:156 90 | msgid "Available Connections" 91 | msgstr "Tillgängliga anslutningar" 92 | 93 | #: src/trayicon.py:364 94 | msgid "Wi-Fi Network Authentication Required" 95 | msgstr "Wi-Fi-nätverksautentisering krävs" 96 | 97 | #: src/trayicon.py:376 98 | #, python-brace-format 99 | msgid "{ssid_info[0]} Wi-Fi Network Authentication failed" 100 | msgstr "Wi-Fi-nätverksautentisering för {ssid_info[0]} misslyckades" 101 | 102 | #: src/trayicon.py:378 103 | #, python-brace-format 104 | msgid "Authentication required by {ssid_info[0]} Wi-Fi Network" 105 | msgstr "Autentisering krävs av Wi-Fi-nätverk {ssid_info[0]}" 106 | 107 | #: src/trayicon.py:381 108 | msgid "Password:" 109 | msgstr "Lösenord:" 110 | 111 | #: src/trayicon.py:384 112 | msgid "Show password" 113 | msgstr "Visa lösenord" 114 | -------------------------------------------------------------------------------- /src/locale/zh_CN/networkmgr.po: -------------------------------------------------------------------------------- 1 | # Language locale/zh translations for PACKAGE package. 2 | # Copyright (C) 2022 THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # SAIHAZE , 2022. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: PACKAGE VERSION\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2022-08-29 15:53+0800\n" 11 | "PO-Revision-Date: 2022-05-02 22:30+0800\n" 12 | "Last-Translator: SAIHAZE \n" 13 | "Language-Team: Language locale/zh\n" 14 | "Language: locale/zh_CN/LC_MESSAGES/networkmgr\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: src/trayicon.py:67 20 | msgid "Ethernet Network" 21 | msgstr "以太网" 22 | 23 | #: src/trayicon.py:78 24 | #, python-format 25 | msgid "Wired %s Connected" 26 | msgstr "有线网络 %s 已连接" 27 | 28 | #: src/trayicon.py:81 29 | #, fuzzy 30 | msgid "Disable" 31 | msgstr "禁用" 32 | 33 | #: src/trayicon.py:86 34 | #, python-format 35 | msgid "Wired %s Disconnected" 36 | msgstr "有线网络 %s 已断开" 37 | 38 | #: src/trayicon.py:89 39 | #, fuzzy 40 | msgid "Enable" 41 | msgstr "启用" 42 | 43 | #: src/trayicon.py:93 44 | #, python-format 45 | msgid "Wired %s Unplug" 46 | msgstr "有线网络 %s 已拔出" 47 | 48 | #: src/trayicon.py:101 49 | #, python-format 50 | msgid "WiFi %s Disabled" 51 | msgstr "无线网络 %s 已禁用" 52 | 53 | #: src/trayicon.py:104 54 | #, python-format 55 | msgid "Enable Wifi %s" 56 | msgstr "启用无线网络 %s" 57 | 58 | #: src/trayicon.py:109 59 | #, python-format 60 | msgid "WiFi %s Disconnected" 61 | msgstr "无线网络 %s 已断开" 62 | 63 | #: src/trayicon.py:113 src/trayicon.py:131 64 | #, python-format 65 | msgid "Disable Wifi %s" 66 | msgstr "禁用无线网络 %s" 67 | 68 | #: src/trayicon.py:119 69 | #, python-format 70 | msgid "WiFi %s Connected" 71 | msgstr "无线网络 %s 已连接" 72 | 73 | #: src/trayicon.py:125 74 | #, python-format 75 | msgid "Disconnect from %s" 76 | msgstr "从 %s 断开" 77 | 78 | #: src/trayicon.py:139 79 | msgid "Enable Networking" 80 | msgstr "启用网络" 81 | 82 | #: src/trayicon.py:143 83 | msgid "Disable Networking" 84 | msgstr "禁用网络" 85 | 86 | #: src/trayicon.py:148 87 | msgid "Close Network Manager" 88 | msgstr "关闭网络管理器" 89 | 90 | #: src/trayicon.py:156 91 | msgid "Available Connections" 92 | msgstr "可用连接" 93 | 94 | #: src/trayicon.py:364 95 | msgid "Wi-Fi Network Authentication Required" 96 | msgstr "无线网络需要认证" 97 | 98 | #: src/trayicon.py:376 99 | #, python-brace-format 100 | msgid "{ssid_info[0]} Wi-Fi Network Authentication failed" 101 | msgstr "{ssid_info[0]} 无线网络认证失败" 102 | 103 | #: src/trayicon.py:378 104 | #, python-brace-format 105 | msgid "Authentication required by {ssid_info[0]} Wi-Fi Network" 106 | msgstr "{ssid_info[0]} 无线网络需要认证" 107 | 108 | #: src/trayicon.py:381 109 | msgid "Password:" 110 | msgstr "密码:" 111 | 112 | #: src/trayicon.py:384 113 | msgid "Show password" 114 | msgstr "展示密码" 115 | -------------------------------------------------------------------------------- /src/networkmgr.conf: -------------------------------------------------------------------------------- 1 | 2 | notify 100 { 3 | match "system" "IFNET"; 4 | match "subsystem" "!(usbus|wlan)[0-9]+"; 5 | match "type" "ATTACH"; 6 | action "/usr/local/share/networkmgr/setup-nic.py $subsystem"; 7 | }; 8 | 9 | notify 100 { 10 | match "system" "IFNET"; 11 | match "type" "LINK_UP"; 12 | media-type "ethernet"; 13 | action "/usr/local/share/networkmgr/link-up.py $subsystem"; 14 | }; 15 | 16 | notify 100 { 17 | match "system" "IFNET"; 18 | match "subsystem" "!(usbus|wlan)[0-9]+"; 19 | match "type" "LINK_DOWN"; 20 | action "/usr/local/share/networkmgr/auto-switch.py $subsystem"; 21 | }; 22 | 23 | attach 100 { 24 | device-name "$wifi-driver-regex"; 25 | action "/usr/local/share/networkmgr/setup-nic.py $device-name"; 26 | }; 27 | -------------------------------------------------------------------------------- /src/networkmgr.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=NetworkMgr 3 | Comment=Network Manager 4 | Exec=sudo networkmgr 5 | Terminal=false 6 | Type=Application 7 | Categories= 8 | NoDisplay=true 9 | X-Mate-Autostart-Notify=true 10 | X-KDE-autostart-after=panel -------------------------------------------------------------------------------- /src/setup-nic.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | import os 4 | import re 5 | import shutil 6 | import sys 7 | from pathlib import Path 8 | from subprocess import Popen, PIPE 9 | 10 | 11 | def file_content(paths): 12 | buffers = [] 13 | for path in paths: 14 | with path.open('r') as file: 15 | buffers.append(file.read()) 16 | return "".join(buffers) 17 | 18 | 19 | args = sys.argv 20 | if len(args) != 2: 21 | exit(1) 22 | nic = args[1] 23 | 24 | etc = Path(os.sep, "etc") 25 | rc_conf = etc / "rc.conf" 26 | rc_conf_local = etc / "rc.conf.local" 27 | wpa_supplicant = etc / "wpa_supplicant.conf" 28 | 29 | rc_conf_paths = [rc_conf] 30 | 31 | if rc_conf_local.exists(): 32 | rc_conf_paths.append(rc_conf_local) 33 | 34 | rc_conf_content = file_content(rc_conf_paths) 35 | 36 | not_nics_regex = "(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|" \ 37 | "ppp|bridge|wg|wlan)[0-9]+|vm-[a-z]+" 38 | 39 | # wifi_driver_regex is taken from devd.conf wifi-driver-regex 40 | wifi_driver_regex = "(ath|ath[0-9]+k|bwi|bwn|ipw|iwlwifi|iwi|iwm|iwn|malo|mwl|mt79|otus|" \ 41 | "ral|rsu|rtw|rtwn|rum|run|uath|upgt|ural|urtw|wpi|wtap|zyd)[0-9]+" 42 | 43 | if re.search(not_nics_regex, nic): 44 | exit(0) 45 | 46 | if re.search(wifi_driver_regex, nic): 47 | if not wpa_supplicant.exists(): 48 | wpa_supplicant.touch() 49 | shutil.chown(wpa_supplicant, user="root", group="wheel") 50 | wpa_supplicant.chmod(0o765) 51 | for wlanNum in range(0, 9): 52 | if f'wlan{wlanNum}' not in rc_conf_content: 53 | if f'wlans_{nic}=' not in rc_conf_content: 54 | with rc_conf.open('a') as rc: 55 | rc.writelines(f'wlans_{nic}="wlan{wlanNum}"\n') 56 | rc.writelines(f'ifconfig_wlan{wlanNum}="WPA DHCP"\n') 57 | break 58 | else: 59 | if f'ifconfig_{nic}=' not in rc_conf_content: 60 | with rc_conf.open('a') as rc: 61 | rc.writelines(f'ifconfig_{nic}="DHCP"\n') 62 | with open(f'/tmp/network-{nic}', 'w') as network: 63 | network.writelines(f'attached') 64 | 65 | Popen(f'/etc/pccard_ether {nic} startchildren', shell=True) 66 | -------------------------------------------------------------------------------- /src/sudoers.d/networkmgr: -------------------------------------------------------------------------------- 1 | %wheel ALL=(ALL) NOPASSWD: /usr/local/bin/networkmgr 2 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Testing networkmgr modules 2 | 3 | Testing networkmgr modules with pytest 4 | 5 | 1. Create a virtual environment using python 3.8 6 | 2. Activate the venv 7 | 3. Install pytest and pytest coverage 8 | 4. Execute pip list to verify your environment. 9 | 10 | ```bash 11 | python3.8 -m venv venv38 12 | 13 | source venv38/bin/activate 14 | 15 | pip install pytest pytest-cov 16 | 17 | networkmgr-fork/tests on  unit_tests [!?] via 🐍 v3.8.12 (venv38) 18 | ❯ pip list 19 | Package Version 20 | ---------- ------- 21 | attrs 21.2.0 22 | coverage 6.2 23 | iniconfig 1.1.1 24 | packaging 21.3 25 | pip 21.3.1 26 | pluggy 1.0.0 27 | py 1.11.0 28 | pyparsing 3.0.6 29 | pytest 6.2.5 30 | pytest-cov 3.0.0 31 | setuptools 60.1.0 32 | sqlite3 0.0.0 33 | Tkinter 0.0.0 34 | toml 0.10.2 35 | tomli 2.0.0 36 | ``` 37 | 38 | To run the tests navigate to the tests directory and enter the following command, 39 | 40 | ```bash 41 | pytest -lv --cov src unit/ 42 | ``` 43 | 44 | The result will be similar to this, 45 | 46 | ```bash 47 | ❯ pytest -lv --cov src unit/ 48 | ================================================== test session starts =================================================== 49 | platform freebsd13 -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /usr/home//venv38/bin/python3.8 50 | cachedir: .pytest_cache 51 | rootdir: /usr/home/rgeorgia/PycharmProjects/networkmgr-fork 52 | plugins: cov-3.0.0 53 | collected 7 items 54 | 55 | unit/test_net_api.py::test_default_card_returns_str PASSED [ 14%] 56 | unit/test_net_api.py::test_card_online PASSED [ 28%] 57 | unit/test_net_api.py::test_card_not_online PASSED [ 42%] 58 | unit/test_net_api.py::test_connection_status_card_is_none PASSED [ 57%] 59 | unit/test_net_api.py::test_connection_status_card_is_default PASSED [ 71%] 60 | unit/test_net_api.py::test_connection_status_card_is_wlan_not_connected PASSED [ 85%] 61 | unit/test_net_api.py::test_connection_status_card_is_wlan_connected PASSED [100%] 62 | 63 | -------- coverage: platform freebsd13, python 3.8.12-final-0 --------- 64 | Name Stmts Miss Cover 65 | --------------------------------------------------------------------------------------- 66 | /usr/home//networkmgr-fork/src/net_api.py 199 119 40% 67 | --------------------------------------------------------------------------------------- 68 | TOTAL 199 119 40% 69 | 70 | 71 | =================================================== 7 passed in 0.11s ==================================================== 72 | 73 | 74 | ``` 75 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostbsd/networkmgr/a09e38e78413716e46d600a59a0d04ec78e8bd75/tests/__init__.py -------------------------------------------------------------------------------- /tests/unit/test_net_api.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pathlib import Path 3 | from subprocess import Popen 4 | import subprocess 5 | 6 | import pytest 7 | 8 | top_dir = str(Path(__file__).absolute().parent.parent.parent) 9 | 10 | try: 11 | from src.net_api import ( 12 | card_online, 13 | connectionStatus, 14 | connectToSsid, 15 | defaultcard, 16 | delete_ssid_wpa_supplicant_config, 17 | disableWifi, 18 | enableWifi, 19 | networkdictionary, 20 | openrc, 21 | startallnetwork, 22 | startnetworkcard, 23 | stopallnetwork, 24 | stopnetworkcard, 25 | wifiDisconnection, 26 | wlan_status, 27 | ) 28 | import src.net_api 29 | except ImportError: 30 | sys.path.append(top_dir) 31 | from src.net_api import ( 32 | card_online, 33 | connectionStatus, 34 | connectToSsid, 35 | defaultcard, 36 | delete_ssid_wpa_supplicant_config, 37 | disableWifi, 38 | enableWifi, 39 | networkdictionary, 40 | openrc, 41 | startallnetwork, 42 | startnetworkcard, 43 | stopallnetwork, 44 | stopnetworkcard, 45 | wifiDisconnection, 46 | wlan_status, 47 | ) 48 | import src.net_api 49 | 50 | 51 | def test_default_card_returns_str(): 52 | """test for src.net_api.defaultcard""" 53 | result = defaultcard() 54 | assert isinstance(result, str) 55 | 56 | 57 | # TODO: mock subprocess to return empty list 58 | 59 | def test_card_online(): 60 | net_card = defaultcard() 61 | result = card_online(net_card) 62 | assert result 63 | 64 | 65 | def test_card_not_online(): 66 | net_card = "em99" 67 | result = card_online(net_card) 68 | assert not result 69 | 70 | 71 | def test_connection_status_card_is_none(): 72 | """test for src.net_api.connectionStatus""" 73 | card = None 74 | result = connectionStatus(card) 75 | assert isinstance(result, str) 76 | assert "Network card is not enabled" == result 77 | 78 | 79 | def test_connection_status_card_is_default(): 80 | """test for src.net_api.connectionStatus""" 81 | card = defaultcard() 82 | result = connectionStatus(card) 83 | assert isinstance(result, str) 84 | assert "inet" in result 85 | assert "netmask" in result 86 | assert "broadcast" in result 87 | 88 | 89 | def test_connection_status_card_is_wlan_not_connected(): 90 | """test for src.net_api.connectionStatus""" 91 | card = 'wlan99' 92 | result = connectionStatus(card) 93 | assert isinstance(result, str) 94 | assert f"WiFi {card} not connected" in result 95 | 96 | 97 | def test_connection_status_card_is_wlan_connected(): 98 | """test for src.net_api.connectionStatus""" 99 | card = 'wlan0' 100 | result = connectionStatus(card) 101 | assert isinstance(result, str) 102 | assert "inet" in result 103 | assert "ssid" in result 104 | assert "netmask" in result 105 | assert "broadcast" in result 106 | -------------------------------------------------------------------------------- /update_translations.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | xgettext src/trayicon.py -o src/locale/networkmgr.pot 4 | 5 | msgmerge -U src/locale/zh_CN/networkmgr.po src/locale/networkmgr.pot 6 | msgmerge -U src/locale/ru/networkmgr.po src/locale/networkmgr.pot 7 | --------------------------------------------------------------------------------