From ffde6a4a043e44d1866d60fe62c4f968a4c7da1e Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Mon, 27 Aug 2012 13:09:22 +0200 Subject: [PATCH] Add use of netifaces to show multiple IP addresses --- src/calibre/gui2/actions/device.py | 16 ++++++-- src/calibre/gui2/dialogs/smartdevice.py | 46 ++++++++++++++++++++++ src/calibre/gui2/dialogs/smartdevice.ui | 51 ++++++++++++++++--------- 3 files changed, 92 insertions(+), 21 deletions(-) diff --git a/src/calibre/gui2/actions/device.py b/src/calibre/gui2/actions/device.py index d978f9723f..92fc34b105 100644 --- a/src/calibre/gui2/actions/device.py +++ b/src/calibre/gui2/actions/device.py @@ -237,20 +237,28 @@ class ConnectShareAction(InterfaceAction): self.share_conn_menu.hide_smartdevice_menus() def set_smartdevice_action_state(self): - from calibre.utils.mdns import get_external_ip + from calibre.gui2.dialogs.smartdevice import get_all_ip_addresses dm = self.gui.device_manager + all_ips = get_all_ip_addresses() + if len(all_ips) > 3: + formatted_addresses = _('Many IP addresses. See Start/Stop dialog.') + show_port = False + else: + formatted_addresses = ' or '.join(get_all_ip_addresses()) + show_port = True + running = dm.is_running('smartdevice') if not running: text = self.share_conn_menu.DEVICE_MSGS[0] else: use_fixed_port = dm.get_option('smartdevice', 'use_fixed_port') port_number = dm.get_option('smartdevice', 'port_number') - if use_fixed_port: + if show_port and use_fixed_port: text = self.share_conn_menu.DEVICE_MSGS[1] + ' [%s port %s]'%( - get_external_ip(), port_number) + formatted_addresses, port_number) else: - text = self.share_conn_menu.DEVICE_MSGS[1] + ' [%s]'%get_external_ip() + text = self.share_conn_menu.DEVICE_MSGS[1] + ' [' + formatted_addresses + ']' icon = 'green' if running else 'red' ac = self.share_conn_menu.control_smartdevice_action diff --git a/src/calibre/gui2/dialogs/smartdevice.py b/src/calibre/gui2/dialogs/smartdevice.py index ea4f6741aa..e3028cb6e1 100644 --- a/src/calibre/gui2/dialogs/smartdevice.py +++ b/src/calibre/gui2/dialogs/smartdevice.py @@ -5,12 +5,47 @@ from __future__ import (unicode_literals, division, absolute_import, __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' +import netifaces, socket + from PyQt4.Qt import (QDialog, QLineEdit, Qt) from calibre.gui2 import error_dialog from calibre.gui2.dialogs.smartdevice_ui import Ui_Dialog from calibre.utils.config import prefs +def _cmp_ipaddr(l, r): + lparts = ['%3s'%x for x in l.split('.')] + rparts = ['%3s'%x for x in r.split('.')] + + if lparts[0] in ['192', '170', ' 10']: + if rparts[0] not in ['192', '170', '10']: + return -1 + return cmp(rparts, lparts) + + if rparts[0] in ['192', '170', ' 10']: + return 1 + + return cmp(lparts, rparts) + +def get_all_ip_addresses(): + ip_info = [netifaces.ifaddresses(x).get(netifaces.AF_INET, None) + for x in netifaces.interfaces()] + + all_ipaddrs = list() + for iface in ip_info: + if iface is not None: + for addrs in iface: + if 'netmask' in addrs and addrs['addr'] != '127.0.0.1': + # We get VPN interfaces that were connected and then + # disconnected. Oh well. At least the 'right' IP addr + # is there. + all_ipaddrs.append(addrs['addr']) + + all_ipaddrs.sort(cmp=_cmp_ipaddr) + print(all_ipaddrs) + return all_ipaddrs + + class SmartdeviceDialog(QDialog, Ui_Dialog): def __init__(self, parent): @@ -49,6 +84,15 @@ class SmartdeviceDialog(QDialog, Ui_Dialog): 'choice at Preferences -> Send to device -> Metadata management') + '

') + self.ip_addresses.setToolTip('

' + + _('These are the IP addresses detected by calibre for the computer ' + 'running calibre. If you decide to have your device connect to ' + 'calibre using a fixed IP address, one of these addresses should ' + 'be the one you use. It is unlikely but possible that the correct ' + 'IP address is not listed here, in which case you will need to go ' + "to your computer's control panel to get a complete list of " + "your computer's network interfaces and IP addresses.") + '

') + self.show_password.stateChanged[int].connect(self.toggle_password) self.use_fixed_port.stateChanged[int].connect(self.use_fixed_port_changed) @@ -79,6 +123,8 @@ class SmartdeviceDialog(QDialog, Ui_Dialog): self.enable_auto_management_box.setEnabled(False) self.auto_management_is_set = True + self.ip_addresses.setText(', '.join(get_all_ip_addresses())) + self.resize(self.sizeHint()) def use_fixed_port_changed(self, state): diff --git a/src/calibre/gui2/dialogs/smartdevice.ui b/src/calibre/gui2/dialogs/smartdevice.ui index fadcf921b4..a8cd546aff 100644 --- a/src/calibre/gui2/dialogs/smartdevice.ui +++ b/src/calibre/gui2/dialogs/smartdevice.ui @@ -38,7 +38,34 @@ + + + + Calibre's IP addresses: + + + + + + Possibe IP addresses: + + + true + + + + + + + Optional &password: + + + password_box + + + + @@ -54,24 +81,14 @@ - - - - Optional &password: - - - password_box - - - - + &Show password - + Optional &fixed port: @@ -81,7 +98,7 @@ - + @@ -94,28 +111,28 @@ - + &Use a fixed port - + &Automatically allow connections at calibre startup - + &Enable automatic sending of book metadata when your device connects - + Qt::Horizontal