Merge branch 'master' into finnish
Conflicts: po/solaar.pot - run tools/po-compile.sh
This commit is contained in:
commit
372e4e0949
|
@ -1,3 +1,10 @@
|
|||
0.9.3:
|
||||
* Merged solaar-cli functionality into main solaar.
|
||||
* Scrolling over the systray icon switches between multiple peripherals.
|
||||
* Swedish translation courtesy of Daniel Zippert and Emelie Snecker
|
||||
* French translation courtesy of Papoteur, David Geiger and Damien Lallement.
|
||||
* Fixed some untranslated strings.
|
||||
|
||||
0.9.2:
|
||||
* Added support for hand detection on the K800.
|
||||
* Added support for V550 and V450 Nano.
|
||||
|
|
10
README.md
10
README.md
|
@ -28,14 +28,16 @@ Pre-built packages are available for a few Linux distros.
|
|||
The `solaar` package uses a standard system tray implementation; to ensure
|
||||
integration with *gnome-shell* or *Unity*, install `solaar-gnome3`.
|
||||
|
||||
* a [Gentoo overlay][gentoo], courtesy of Carlos Silva
|
||||
* an [OpenSUSE rpm][opensuse], courtesy of Mathias Homann
|
||||
* an [Arch package][arch], courtesy of Arnaud Taffanel
|
||||
* a [Gentoo overlay][gentoo], courtesy of Carlos Silva
|
||||
* a [Mageia package][mageia], courtesy of Damien Lallement
|
||||
* an [OpenSUSE rpm][opensuse], courtesy of Mathias Homann
|
||||
|
||||
[ppa]: http://launchpad.net/~daniel.pavel/+archive/solaar
|
||||
[gentoo]: http://code.r3pek.org/gentoo-overlay/src
|
||||
[opensuse]: http://software.opensuse.org/package/Solaar
|
||||
[arch]: http://aur.archlinux.org/packages/solaar
|
||||
[gentoo]: http://code.r3pek.org/gentoo-overlay/src
|
||||
[mageia]: http://mageia.madb.org/package/show/release/cauldron/application/0/name/solaar
|
||||
[opensuse]: http://software.opensuse.org/package/Solaar
|
||||
|
||||
|
||||
## Manual installation
|
||||
|
|
|
@ -37,6 +37,7 @@ def init_paths():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print ('WARNING: solaar-cli is deprecated; use solaar with the usual arguments')
|
||||
init_paths()
|
||||
import solaar.cli
|
||||
solaar.cli.main()
|
||||
solaar.cli.run()
|
||||
|
|
|
@ -40,9 +40,6 @@ Solaar, but its supported features are not specified here, I would love to hear
|
|||
about it.
|
||||
|
||||
|
||||
Devices marked with an asterisk (*) use a Nano receiver that knows the Unifying
|
||||
protocol, and should be fully supported by Solaar.
|
||||
|
||||
The HID++ column specifies the device's HID++ version.
|
||||
|
||||
The Battery column specifies if Solaar is able to read the device's battery
|
||||
|
@ -56,14 +53,14 @@ You are able to read this feature using solaar-cli, but it is not possible to
|
|||
assign different keys.
|
||||
|
||||
|
||||
Keyboards:
|
||||
Keyboards (Unifying):
|
||||
|
||||
| Device | HID++ | Battery | Other supported features |
|
||||
|------------------|-------|---------|-----------------------------------------|
|
||||
| K230 | 2.0 | yes | |
|
||||
| K270 | | | |
|
||||
| K340 | | | |
|
||||
| K350 | | | |
|
||||
| K270 | 1.0 | yes | |
|
||||
| K340 | 1.0 | yes | |
|
||||
| K350 | 1.0 | yes | |
|
||||
| K360 | 2.0 | yes | FN swap, reprog keys |
|
||||
| K400 Touch | 2.0 | yes | |
|
||||
| K750 Solar | 2.0 | yes | FN swap, Lux reading, light button |
|
||||
|
@ -71,50 +68,70 @@ Keyboards:
|
|||
| MK700 | 1.0 | yes | FN swap, reprog keys |
|
||||
|
||||
|
||||
Mice:
|
||||
Mice (Unifying):
|
||||
|
||||
| Device | HID++ | Battery | DPI | Other supported features |
|
||||
|------------------|-------|---------|-------|---------------------------------|
|
||||
| V450 Nano | 1.0 | yes | - | smooth scrolling |
|
||||
| V550 Nano | 1.0 | yes | - | smooth scrolling |
|
||||
| VX Nano | 1.0 | yes | - | smooth scrolling |
|
||||
| M175 * | | yes | | |
|
||||
| M185 * | | yes | | |
|
||||
| M187 * | 2.0 | yes | | |
|
||||
| M215 * | 1.0 | yes | | |
|
||||
| M235 * | | yes | | |
|
||||
| M305 * | 1.0 | yes | | |
|
||||
| M310 * | | yes | | |
|
||||
| M315 * | | yes | | |
|
||||
| M317 | | | | |
|
||||
| M325 | | | | |
|
||||
| M345 | 2.0 | yes | - | |
|
||||
| M505 | 1.0 | yes | | |
|
||||
| M350 | 1.0 | yes | | |
|
||||
| M505 | 1.0 | yes | | smooth scrolling |
|
||||
| M510 | 1.0 | yes | | smooth scrolling |
|
||||
| M515 Couch | 2.0 | yes | - | |
|
||||
| M525 | 2.0 | yes | - | |
|
||||
| M600 Touch | 2.0 | yes | | |
|
||||
| M705 Marathon | 1.0 | yes | - | smooth scrolling |
|
||||
| T400 Zone Touch | | | | |
|
||||
| T620 Touch | 2.0 | | | |
|
||||
| T620 Touch | 2.0 | yes | | |
|
||||
| Performance MX | 1.0 | yes | R/W | |
|
||||
| Anywhere MX | 1.0 | yes | - | |
|
||||
| Cube | 2.0 | yes | | |
|
||||
|
||||
|
||||
Trackballs:
|
||||
Mice (Nano):
|
||||
|
||||
| Device | HID++ | Battery | DPI | Other supported features |
|
||||
|------------------|-------|---------|-------|---------------------------------|
|
||||
| V450 Nano | 1.0 | yes | - | smooth scrolling |
|
||||
| V550 Nano | 1.0 | yes | - | smooth scrolling |
|
||||
| VX Nano | 1.0 | yes | - | smooth scrolling |
|
||||
| M175 | | yes | | |
|
||||
| M185 | | yes | | |
|
||||
| M187 | 2.0 | yes | | |
|
||||
| M215 | 1.0 | yes | | |
|
||||
| M235 | | yes | | |
|
||||
| M305 | 1.0 | yes | | |
|
||||
| M310 | 1.0 | yes | | |
|
||||
| M315 | | yes | | |
|
||||
|
||||
|
||||
Mice (Mini):
|
||||
|
||||
| Device | HID++ | Battery | DPI | Other supported features |
|
||||
|------------------|-------|---------|-------|---------------------------------|
|
||||
| MX610 | 1.0 | yes | | |
|
||||
| MX610 lefthanded | 1.0 | yes | | |
|
||||
| V400 | 1.0 | yes | | |
|
||||
| V450 | 1.0 | yes | | |
|
||||
| VX Revolution | 1.0 | yes | | |
|
||||
| MX Air | 1.0 | yes | | |
|
||||
| MX Revolution | 1.0 | yes | | |
|
||||
|
||||
|
||||
Trackballs (Unifying):
|
||||
|
||||
| Device | HID++ | Battery | DPI | Other supported features |
|
||||
|------------------|-------|---------|-------|---------------------------------|
|
||||
| M570 Trackball | | | | |
|
||||
|
||||
|
||||
Touchpads:
|
||||
Touchpads (Unifying):
|
||||
|
||||
| Device | HID++ | Battery | DPI | Other supported features |
|
||||
|------------------|-------|---------|-------|---------------------------------|
|
||||
| Wireless Touch | 2.0 | | | |
|
||||
| T650 Touchpad | 2.0 | | | |
|
||||
| Wireless Touch | 2.0 | yes | | |
|
||||
| T650 Touchpad | 2.0 | yes | | |
|
||||
|
||||
|
||||
Mouse-Keyboard combos:
|
||||
|
|
21
docs/i18n.md
21
docs/i18n.md
|
@ -28,3 +28,24 @@ the source root):
|
|||
|
||||
You can edit the translation iteratively, just repeat from step 3.
|
||||
If the upstream changes, do a `git pull` and then repeat from step 2.
|
||||
|
||||
Before opening a pull request, please run `./tools/po-update.sh` again. It will
|
||||
format and sort the translation file, and ensure a minimal diff when updating
|
||||
a translation.
|
||||
|
||||
|
||||
# Supported languages
|
||||
|
||||
Currently Solaar has been translated in the following languages:
|
||||
|
||||
- Français: [Papoteur][papoteur], [David Geiger][david-geiger],
|
||||
[Damien Lallement][damsweb]
|
||||
- Polski: [Adrian Piotrowicz][nexces]
|
||||
- Română: Daniel Pavel
|
||||
- Svensk: [Daniel Zippert][zipperten], Emelie Snecker
|
||||
|
||||
[papoteur]: http://github.com/papoteur
|
||||
[david-geiger]: http://github.com/david-geiger
|
||||
[damsweb]: http://github.com/damsweb
|
||||
[nexces]: http://github.com/nexces
|
||||
[zipperten]: http://github.com/zipperten
|
||||
|
|
|
@ -3,8 +3,8 @@ tagline: Linux devices manager for the Logitech Unifying Receiver.
|
|||
owner: pwr
|
||||
owner_url: https://github.com/pwr
|
||||
repository: https://github.com/pwr/Solaar
|
||||
version: 0.9.1
|
||||
tar_download: https://github.com/pwr/Solaar/archive/0.9.1.tar.gz
|
||||
version: 0.9.2
|
||||
tar_download: https://github.com/pwr/Solaar/archive/0.9.2.tar.gz
|
||||
ga_id: UA-36908718-1
|
||||
|
||||
pygments: true
|
||||
|
|
|
@ -28,30 +28,33 @@ _GENERIC_DRIVER = ('hid-generic', 'generic-usb')
|
|||
|
||||
|
||||
# each tuple contains (vendor_id, product_id, usb interface number, hid driver)
|
||||
_unifying_receiver = lambda product_id: (0x046d, product_id, 2, _UNIFYING_DRIVER)
|
||||
_nano_receiver = lambda product_id: (0x046d, product_id, 1, _GENERIC_DRIVER)
|
||||
|
||||
|
||||
# standard Unifying receivers (marked with the orange Unifying logo)
|
||||
UNIFYING_RECEIVER = (0x046d, 0xc52b, 2, _UNIFYING_DRIVER)
|
||||
UNIFYING_RECEIVER_2 = (0x046d, 0xc532, 2, _UNIFYING_DRIVER)
|
||||
|
||||
|
||||
UNIFYING_RECEIVER_C52B = _unifying_receiver(0xc52b)
|
||||
UNIFYING_RECEIVER_C532 = _unifying_receiver(0xc532)
|
||||
|
||||
# Nano receviers that support the Unifying protocol
|
||||
NANO_RECEIVER_ADVANCED = (0x046d, 0xc52f, 1, _GENERIC_DRIVER)
|
||||
NANO_RECEIVER_ADVANCED = _nano_receiver(0xc52f)
|
||||
|
||||
# Nano receivers that don't support the Unifying protocol
|
||||
NANO_RECEIVER_C517 = (0x046d, 0xc517, 1, _GENERIC_DRIVER)
|
||||
NANO_RECEIVER_C518 = (0x046d, 0xc518, 1, _GENERIC_DRIVER)
|
||||
NANO_RECEIVER_C51A = (0x046d, 0xc51a, 1, _GENERIC_DRIVER)
|
||||
NANO_RECEIVER_C51B = (0x046d, 0xc51b, 1, _GENERIC_DRIVER)
|
||||
NANO_RECEIVER_C521 = (0x046d, 0xc521, 1, _GENERIC_DRIVER)
|
||||
NANO_RECEIVER_C525 = (0x046d, 0xc525, 1, _GENERIC_DRIVER)
|
||||
NANO_RECEIVER_C526 = (0x046d, 0xc526, 1, _GENERIC_DRIVER)
|
||||
NANO_RECEIVER_C517 = _nano_receiver(0xc517)
|
||||
NANO_RECEIVER_C518 = _nano_receiver(0xc518)
|
||||
NANO_RECEIVER_C51A = _nano_receiver(0xc51a)
|
||||
NANO_RECEIVER_C51B = _nano_receiver(0xc51b)
|
||||
NANO_RECEIVER_C521 = _nano_receiver(0xc521)
|
||||
NANO_RECEIVER_C525 = _nano_receiver(0xc525)
|
||||
NANO_RECEIVER_C526 = _nano_receiver(0xc526)
|
||||
|
||||
|
||||
del _unifying_receiver, _nano_receiver
|
||||
|
||||
|
||||
ALL = (
|
||||
UNIFYING_RECEIVER,
|
||||
UNIFYING_RECEIVER_2,
|
||||
UNIFYING_RECEIVER_C52B,
|
||||
UNIFYING_RECEIVER_C532,
|
||||
NANO_RECEIVER_ADVANCED,
|
||||
NANO_RECEIVER_C517,
|
||||
NANO_RECEIVER_C518,
|
||||
|
|
|
@ -20,12 +20,10 @@
|
|||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
|
||||
from . import hidpp10 as _hidpp10
|
||||
from .common import NamedInts as _NamedInts
|
||||
from .hidpp10 import REGISTERS as _R, DEVICE_KIND as _DK
|
||||
from .settings_templates import RegisterSettings as _RS, FeatureSettings as _FS
|
||||
|
||||
_R = _hidpp10.REGISTERS
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
@ -41,10 +39,11 @@ def _D(name, codename=None, kind=None, wpid=None, protocol=None, registers=None,
|
|||
assert name
|
||||
|
||||
if kind is None:
|
||||
kind = (_hidpp10.DEVICE_KIND.mouse if 'Mouse' in name
|
||||
else _hidpp10.DEVICE_KIND.keyboard if 'Keyboard' in name
|
||||
else _hidpp10.DEVICE_KIND.touchpad if 'Touchpad' in name
|
||||
else _hidpp10.DEVICE_KIND.trackball if 'Trackball' in name
|
||||
kind = (_DK.mouse if 'Mouse' in name
|
||||
else _DK.keyboard if 'Keyboard' in name
|
||||
else _DK.numpad if 'Number Pad' in name
|
||||
else _DK.touchpad if 'Touchpad' in name
|
||||
else _DK.trackball if 'Trackball' in name
|
||||
else None)
|
||||
assert kind is not None, 'descriptor for %s does not have kind set' % name
|
||||
|
||||
|
@ -64,12 +63,12 @@ def _D(name, codename=None, kind=None, wpid=None, protocol=None, registers=None,
|
|||
if wpid:
|
||||
for w in wpid if isinstance(wpid, tuple) else (wpid, ):
|
||||
if protocol > 1.0:
|
||||
assert w[0:1] == '4', name + ' has protocol ' + protocol + ', wpid ' + w
|
||||
assert w[0:1] == '4', '%s has protocol %0.1f, wpid %s' % (name, protocol, w)
|
||||
else:
|
||||
if w[0:1] == '1':
|
||||
assert kind == _hidpp10.DEVICE_KIND.mouse, name + ' has protocol ' + protocol + ', wpid ' + w
|
||||
assert kind == _DK.mouse, '%s has protocol %0.1f, wpid %s' % (name, protocol, w)
|
||||
elif w[0:1] == '2':
|
||||
assert kind == _hidpp10.DEVICE_KIND.keyboard, name + ' has protocol ' + protocol + ', wpid ' + w
|
||||
assert kind in (_DK.keyboard, _DK.numpad), '%s has protocol %0.1f, wpid %s' % (name, protocol, w)
|
||||
|
||||
device_descriptor = _DeviceDescriptor(name=name, kind=kind,
|
||||
wpid=wpid, codename=codename, protocol=protocol,
|
||||
|
@ -144,10 +143,16 @@ _PERFORMANCE_MX_DPIS = _NamedInts.range(0x81, 0x8F, lambda x: str((x - 0x80) * 1
|
|||
# Keyboards
|
||||
|
||||
_D('Wireless Keyboard K230', protocol=2.0, wpid='400D')
|
||||
_D('Wireless Keyboard K270')
|
||||
_D('Wireless Keyboard K270', protocol=1.0,
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('Wireless Keyboard MK330')
|
||||
_D('Wireless Keyboard K340')
|
||||
_D('Wireless Keyboard K350', wpid='200A')
|
||||
_D('Wireless Compact Keyboard K340', protocol=1.0, wpid='2007',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('Wireless Wave Keyboard K350', protocol=1.0, wpid='200A',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('Wireless Keyboard K360', protocol=2.0, wpid='4004',
|
||||
settings=[
|
||||
_FS.fn_swap()
|
||||
|
@ -158,7 +163,15 @@ _D('Wireless Touch Keyboard K400', protocol=2.0, wpid=('400E', '4024'),
|
|||
_FS.fn_swap()
|
||||
],
|
||||
)
|
||||
_D('Wireless Keyboard MK520')
|
||||
_D('Wireless Keyboard K520', protocol=1.0, wpid='2011',
|
||||
registers=(_R.battery_status, ),
|
||||
settings=[
|
||||
_RS.fn_swap(),
|
||||
],
|
||||
)
|
||||
_D('Number Pad N545', protocol=1.0, wpid='2006',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('Wireless Keyboard MK550')
|
||||
_D('Wireless Keyboard MK700', protocol=1.0, wpid='2008',
|
||||
registers=(_R.battery_status, ),
|
||||
|
@ -192,11 +205,16 @@ _D('Wireless Mouse M305', protocol=1.0, wpid='101F',
|
|||
_RS.side_scroll(),
|
||||
],
|
||||
)
|
||||
_D('Wireless Mouse M310')
|
||||
_D('Wireless Mouse M310', protocol=1.0, wpid='1024',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('Wireless Mouse M315')
|
||||
_D('Wireless Mouse M317')
|
||||
_D('Wireless Mouse M325')
|
||||
_D('Wireless Mouse M345', protocol=2.0, wpid='4017')
|
||||
_D('Wireless Mouse M350', protocol=1.0, wpid='101C',
|
||||
registers=(_R.battery_charge, ),
|
||||
)
|
||||
_D('Wireless Mouse M505', codename='M505/B605', protocol=1.0, wpid='101D',
|
||||
registers=(_R.battery_charge, ),
|
||||
settings=[
|
||||
|
@ -223,7 +241,7 @@ _D('Marathon Mouse M705', protocol=1.0, wpid='101B',
|
|||
)
|
||||
_D('Zone Touch Mouse T400')
|
||||
_D('Touch Mouse T620', protocol=2.0)
|
||||
_D('Logitech Cube', kind=_hidpp10.DEVICE_KIND.mouse, protocol=2.0)
|
||||
_D('Logitech Cube', kind=_DK.mouse, protocol=2.0)
|
||||
_D('Anywhere Mouse MX', codename='Anywhere MX', protocol=1.0, wpid='1017',
|
||||
registers=(_R.battery_charge, ),
|
||||
settings=[
|
||||
|
@ -240,6 +258,13 @@ _D('Performance Mouse MX', codename='Performance MX', protocol=1.0, wpid='101A',
|
|||
],
|
||||
)
|
||||
|
||||
_D('G7 Cordless Laser Mouse', codename='G7', protocol=1.0, wpid='1002',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('G700 Gaming Mouse', codename='G700', protocol=1.0, wpid='1023',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
|
||||
# Trackballs
|
||||
|
||||
_D('Wireless Trackball M570')
|
||||
|
@ -254,7 +279,7 @@ _D('Wireless Touchpad', codename='Wireless Touch', protocol=2.0, wpid='4011')
|
|||
# A wpid is necessary to properly identify them.
|
||||
#
|
||||
|
||||
_D('VX Nano Cordless Laser Mouse', codename='VX Nano', protocol=1.0, wpid='100F',
|
||||
_D('VX Nano Cordless Laser Mouse', codename='VX Nano', protocol=1.0, wpid=('100B', '100F'),
|
||||
registers=(_R.battery_charge, ),
|
||||
settings=[
|
||||
_RS.smooth_scroll(),
|
||||
|
@ -271,3 +296,34 @@ _D('V550 Nano Cordless Laser Mouse', codename='V550 Nano', protocol=1.0, wpid='1
|
|||
_RS.side_scroll(),
|
||||
],
|
||||
)
|
||||
|
||||
# Mini receiver mice
|
||||
|
||||
_D('MX610 Laser Cordless Mouse', codename='MX610', protocol=1.0, wpid='1001',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('MX620 Laser Cordless Mouse', codename='MX620', protocol=1.0, wpid=('100A', '1016'),
|
||||
registers=(_R.battery_charge, ),
|
||||
)
|
||||
_D('MX610 Left-Handled Mouse', codename='MX610L', protocol=1.0, wpid='1004',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('V400 Laser Cordless Mouse', codename='V400', protocol=1.0, wpid='1003',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('V450 Laser Cordless Mouse', codename='V450', protocol=1.0, wpid='1005',
|
||||
registers=(_R.battery_status, ),
|
||||
)
|
||||
_D('VX Revolution', codename='VX Revolution', kind=_DK.mouse, protocol=1.0, wpid=('1006', '100D'),
|
||||
registers=(_R.battery_charge, ),
|
||||
)
|
||||
_D('MX Air', codename='MX Air', protocol=1.0, kind=_DK.mouse, wpid=('1007', '100E'),
|
||||
registers=(_R.battery_charge, ),
|
||||
)
|
||||
_D('MX Revolution', codename='MX Revolution', protocol=1.0, kind=_DK.mouse, wpid=('1008', '100C'),
|
||||
registers=(_R.battery_charge, ),
|
||||
)
|
||||
|
||||
# Some exotics...
|
||||
|
||||
_D('Fujitsu Sonic Mouse', codename='Sonic', protocol=1.0, wpid='1029')
|
||||
|
|
|
@ -147,7 +147,7 @@ def _process_hidpp10_notification(device, status, n):
|
|||
device.status = None
|
||||
if device.number in device.receiver:
|
||||
del device.receiver[device.number]
|
||||
status.changed(active=False, alert=_ALERT.ALL, reason='unpaired')
|
||||
status.changed(active=False, alert=_ALERT.ALL, reason=_("unpaired"))
|
||||
else:
|
||||
_log.warn("%s: disconnection with unknown type %02X: %s", device, n.address, n)
|
||||
return True
|
||||
|
|
|
@ -140,13 +140,9 @@ class DeviceStatus(dict):
|
|||
self.updated = 0
|
||||
|
||||
def __str__(self):
|
||||
def _item(name, format):
|
||||
value = self.get(name)
|
||||
if value is not None:
|
||||
return format % value
|
||||
|
||||
def _items():
|
||||
# TODO properly string approximative battery levels
|
||||
comma = False
|
||||
|
||||
battery_level = self.get(KEYS.BATTERY_LEVEL)
|
||||
if battery_level is not None:
|
||||
if isinstance(battery_level, _NamedInt):
|
||||
|
@ -154,20 +150,24 @@ class DeviceStatus(dict):
|
|||
else:
|
||||
yield _("Battery") + ': ' + ('%d%%' % battery_level)
|
||||
|
||||
battery_status = _item(KEYS.BATTERY_STATUS, ' (%s)')
|
||||
if battery_status:
|
||||
yield battery_status
|
||||
battery_status = self.get(KEYS.BATTERY_STATUS)
|
||||
if battery_status is not None:
|
||||
yield ' (%s)' % _(str(battery_status))
|
||||
|
||||
light_level = _item(KEYS.LIGHT_LEVEL, _("Lighting") + ': %d ' + _("lux"))
|
||||
if light_level:
|
||||
if battery_level:
|
||||
yield ', '
|
||||
yield light_level
|
||||
comma = True
|
||||
|
||||
light_level = self.get(KEYS.LIGHT_LEVEL)
|
||||
if light_level is not None:
|
||||
if comma: yield ', '
|
||||
yield _("Lighting") + (': %d ' % light_level) + _("lux")
|
||||
|
||||
return ''.join(i for i in _items())
|
||||
|
||||
__unicode__ = __str__
|
||||
|
||||
def __repr__(self):
|
||||
return '{' + ', '.join('\'%s\': %r' % (k, v) for k, v in self.items()) + '}'
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self._active)
|
||||
__nonzero__ = __bool__
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- python-mode -*-
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
## Copyright (C) 2012-2013 Daniel Pavel
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from logging import getLogger, DEBUG as _DEBUG
|
||||
_log = getLogger(__name__)
|
||||
del getLogger
|
||||
|
||||
from threading import Thread as _Thread
|
||||
|
||||
try:
|
||||
from Queue import Queue as _Queue
|
||||
except ImportError:
|
||||
from queue import Queue as _Queue
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
class TaskRunner(_Thread):
|
||||
def __init__(self, name):
|
||||
super(TaskRunner, self).__init__(name=name)
|
||||
self.daemon = True
|
||||
self.queue = _Queue(16)
|
||||
self.alive = False
|
||||
|
||||
def __call__(self, function, *args, **kwargs):
|
||||
task = (function, args, kwargs)
|
||||
self.queue.put(task)
|
||||
|
||||
def stop(self):
|
||||
self.alive = False
|
||||
self.queue.put(None)
|
||||
|
||||
def run(self):
|
||||
self.alive = True
|
||||
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("started")
|
||||
|
||||
while self.alive:
|
||||
task = self.queue.get()
|
||||
if task:
|
||||
function, args, kwargs = task
|
||||
assert function
|
||||
try:
|
||||
function(*args, **kwargs)
|
||||
except:
|
||||
_log.exception("calling %s", function)
|
||||
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("stopped")
|
|
@ -1,434 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- python-mode -*-
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
## Copyright (C) 2012-2013 Daniel Pavel
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import sys
|
||||
import logging
|
||||
|
||||
|
||||
NAME = 'solaar-cli'
|
||||
from solaar import __version__
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def _fail(text):
|
||||
if sys.exc_info()[0]:
|
||||
logging.exception(text)
|
||||
sys.exit("%s: error: %s" % (NAME, text))
|
||||
|
||||
|
||||
def _require(module, os_package):
|
||||
try:
|
||||
__import__(module)
|
||||
except ImportError:
|
||||
_fail("missing required package '%s'" % os_package)
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def _receiver(dev_path=None):
|
||||
from logitech_receiver import Receiver
|
||||
from logitech_receiver.base import receivers
|
||||
for dev_info in receivers():
|
||||
if dev_path is not None and dev_path != dev_info.path:
|
||||
continue
|
||||
try:
|
||||
r = Receiver.open(dev_info)
|
||||
if r:
|
||||
return r
|
||||
except Exception as e:
|
||||
_fail(str(e))
|
||||
return r
|
||||
_fail("Logitech receiver not found")
|
||||
|
||||
|
||||
def _find_device(receiver, name, may_be_receiver=False):
|
||||
if len(name) == 1:
|
||||
try:
|
||||
number = int(name)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
if number < 1 or number > receiver.max_devices:
|
||||
_fail("%s (%s) supports device numbers 1 to %d" % (receiver.name, receiver.path, receiver.max_devices))
|
||||
dev = receiver[number]
|
||||
if dev is None:
|
||||
_fail("no paired device with number %s" % number)
|
||||
return dev
|
||||
|
||||
if len(name) < 3:
|
||||
_fail("need at least 3 characters to match a device")
|
||||
|
||||
name = name.lower()
|
||||
if may_be_receiver and ('receiver'.startswith(name) or name == receiver.serial.lower()):
|
||||
return receiver
|
||||
|
||||
for dev in receiver:
|
||||
if (name == dev.serial.lower() or
|
||||
name == dev.codename.lower() or
|
||||
name == str(dev.kind).lower() or
|
||||
name in dev.name.lower()):
|
||||
return dev
|
||||
|
||||
_fail("no device found matching '%s'" % name)
|
||||
|
||||
|
||||
def _print_receiver(receiver, verbose=False):
|
||||
paired_count = receiver.count()
|
||||
if not verbose:
|
||||
print ("Unifying Receiver [%s:%s] with %d devices" % (receiver.path, receiver.serial, paired_count))
|
||||
return
|
||||
|
||||
print ("Unifying Receiver")
|
||||
print (" Device path :", receiver.path)
|
||||
print (" USB id : 046d:%s" % receiver.product_id)
|
||||
print (" Serial :", receiver.serial)
|
||||
for f in receiver.firmware:
|
||||
print (" %-11s: %s" % (f.kind, f.version))
|
||||
|
||||
print (" Has", paired_count, "paired device(s) out of a maximum of", receiver.max_devices, ".")
|
||||
|
||||
from logitech_receiver import hidpp10
|
||||
notification_flags = hidpp10.get_notification_flags(receiver)
|
||||
if notification_flags is not None:
|
||||
if notification_flags:
|
||||
notification_names = hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
||||
print (" Notifications: 0x%06X = %s" % (notification_flags, ', '.join(notification_names)))
|
||||
else:
|
||||
print (" Notifications: (none)")
|
||||
|
||||
activity = receiver.read_register(hidpp10.REGISTERS.devices_activity)
|
||||
if activity:
|
||||
activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)]
|
||||
activity_text = ', '.join(('%d=%d' % (d, a)) for d, a in activity if a > 0)
|
||||
print (" Device activity counters:", activity_text or '(empty)')
|
||||
|
||||
|
||||
def _print_device(dev, verbose=False):
|
||||
assert dev
|
||||
state = '' if dev.ping() else 'offline'
|
||||
|
||||
if not verbose:
|
||||
print ("%d: %s [%s:%s]" % (dev.number, dev.name, dev.codename, dev.serial), state)
|
||||
return
|
||||
|
||||
print ("%d: %s" % (dev.number, dev.name))
|
||||
print (" Codename :", dev.codename)
|
||||
print (" Kind :", dev.kind)
|
||||
print (" Wireless PID :", dev.wpid)
|
||||
if dev.protocol:
|
||||
print (" Protocol : HID++ %1.1f" % dev.protocol)
|
||||
else:
|
||||
print (" Protocol : unknown (device is offline)")
|
||||
print (" Polling rate :", dev.polling_rate, "ms")
|
||||
print (" Serial number:", dev.serial)
|
||||
for fw in dev.firmware:
|
||||
print (" %11s:" % fw.kind, (fw.name + ' ' + fw.version).strip())
|
||||
|
||||
if dev.power_switch_location:
|
||||
print (" The power switch is located on the %s." % dev.power_switch_location)
|
||||
|
||||
from logitech_receiver import hidpp10, hidpp20, special_keys
|
||||
|
||||
if dev.online:
|
||||
notification_flags = hidpp10.get_notification_flags(dev)
|
||||
if notification_flags is not None:
|
||||
if notification_flags:
|
||||
notification_names = hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
||||
print (" Notifications: 0x%06X = %s." % (notification_flags, ', '.join(notification_names)))
|
||||
else:
|
||||
print (" Notifications: (none).")
|
||||
|
||||
if dev.online:
|
||||
if dev.features:
|
||||
print (" Supports %d HID++ 2.0 features:" % len(dev.features))
|
||||
for index, feature in enumerate(dev.features):
|
||||
feature = dev.features[index]
|
||||
flags = dev.request(0x0000, feature.bytes(2))
|
||||
flags = 0 if flags is None else ord(flags[1:2])
|
||||
flags = hidpp20.FEATURE_FLAG.flag_names(flags)
|
||||
print (" %2d: %-22s {%04X} %s" % (index, feature, feature, ', '.join(flags)))
|
||||
|
||||
if dev.online:
|
||||
if dev.keys:
|
||||
print (" Has %d reprogrammable keys:" % len(dev.keys))
|
||||
for k in dev.keys:
|
||||
flags = special_keys.KEY_FLAG.flag_names(k.flags)
|
||||
print (" %2d: %-26s => %-27s %s" % (k.index, k.key, k.task, ', '.join(flags)))
|
||||
|
||||
if dev.online:
|
||||
battery = hidpp20.get_battery(dev)
|
||||
if battery is None:
|
||||
battery = hidpp10.get_battery(dev)
|
||||
if battery is not None:
|
||||
from logitech_receiver.common import NamedInt as _NamedInt
|
||||
level, status = battery
|
||||
if isinstance(level, _NamedInt):
|
||||
text = str(level)
|
||||
else:
|
||||
text = '%d%%' % level
|
||||
print (" Battery: %s, %s," % (text, status))
|
||||
else:
|
||||
print (" Battery status unavailable.")
|
||||
else:
|
||||
print (" Battery status is unknown (device is offline).")
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def show_devices(receiver, args):
|
||||
if args.device == 'all':
|
||||
_print_receiver(receiver, args.verbose)
|
||||
for dev in receiver:
|
||||
if args.verbose:
|
||||
print ("")
|
||||
_print_device(dev, args.verbose)
|
||||
else:
|
||||
dev = _find_device(receiver, args.device, True)
|
||||
if dev is receiver:
|
||||
_print_receiver(receiver, args.verbose)
|
||||
else:
|
||||
_print_device(dev, args.verbose)
|
||||
|
||||
|
||||
def pair_device(receiver, args):
|
||||
# get all current devices
|
||||
known_devices = [dev.number for dev in receiver]
|
||||
|
||||
from logitech_receiver import base, hidpp10, status, notifications
|
||||
receiver.status = status.ReceiverStatus(receiver, lambda *args, **kwargs: None)
|
||||
|
||||
# check if it's necessary to set the notification flags
|
||||
old_notification_flags = hidpp10.get_notification_flags(receiver) or 0
|
||||
if not (old_notification_flags & hidpp10.NOTIFICATION_FLAG.wireless):
|
||||
hidpp10.set_notification_flags(receiver, old_notification_flags | hidpp10.NOTIFICATION_FLAG.wireless)
|
||||
|
||||
class HandleWithNotificationHook(int):
|
||||
def notifications_hook(self, n):
|
||||
assert n
|
||||
if n.devnumber == 0xFF:
|
||||
notifications.process(receiver, n)
|
||||
elif n.sub_id == 0x41 and n.address == 0x04:
|
||||
if n.devnumber not in known_devices:
|
||||
receiver.status.new_device = receiver[n.devnumber]
|
||||
|
||||
timeout = 20 # seconds
|
||||
receiver.handle = HandleWithNotificationHook(receiver.handle)
|
||||
receiver.set_lock(False, timeout=timeout)
|
||||
print ("Pairing: turn your new device on (timing out in", timeout, "seconds).")
|
||||
|
||||
# the lock-open notification may come slightly later, wait for it a bit
|
||||
from time import time as timestamp
|
||||
pairing_start = timestamp()
|
||||
patience = 5 # seconds
|
||||
|
||||
while receiver.status.lock_open or timestamp() - pairing_start < patience:
|
||||
n = base.read(receiver.handle)
|
||||
if n:
|
||||
n = base.make_notification(*n)
|
||||
if n:
|
||||
receiver.handle.notifications_hook(n)
|
||||
|
||||
if not (old_notification_flags & hidpp10.NOTIFICATION_FLAG.wireless):
|
||||
# only clear the flags if they weren't set before, otherwise a
|
||||
# concurrently running Solaar app might stop working properly
|
||||
hidpp10.set_notification_flags(receiver, old_notification_flags)
|
||||
|
||||
if receiver.status.new_device:
|
||||
dev = receiver.status.new_device
|
||||
print ("Paired device %d: %s [%s:%s:%s]" % (dev.number, dev.name, dev.wpid, dev.codename, dev.serial))
|
||||
else:
|
||||
error = receiver.status[status.KEYS.ERROR] or 'no device detected?'
|
||||
_fail(error)
|
||||
|
||||
|
||||
def unpair_device(receiver, args):
|
||||
dev = _find_device(receiver, args.device)
|
||||
|
||||
# query these now, it's last chance to get them
|
||||
number, name, codename, serial = dev.number, dev.name, dev.codename, dev.serial
|
||||
try:
|
||||
del receiver[number]
|
||||
print ("Unpaired %d: %s [%s:%s]" % (number, name, codename, serial))
|
||||
except Exception as e:
|
||||
_fail("failed to unpair device %s: %s" % (dev.name, e))
|
||||
|
||||
|
||||
def config_device(receiver, args):
|
||||
dev = _find_device(receiver, args.device)
|
||||
# if dev is receiver:
|
||||
# _fail("no settings for the receiver")
|
||||
|
||||
if not dev.settings:
|
||||
_fail("no settings for %s" % dev.name)
|
||||
|
||||
if not args.setting:
|
||||
print ("[%s:%s]" % (dev.serial, dev.kind))
|
||||
print ("#", dev.name)
|
||||
for s in dev.settings:
|
||||
print ("")
|
||||
print ("# %s" % s.label)
|
||||
if s.choices:
|
||||
print ("# possible values: one of [", ', '.join(str(v) for v in s.choices), "], or higher/lower/highest/max/lowest/min")
|
||||
else:
|
||||
print ("# possible values: on/true/t/yes/y/1 or off/false/f/no/n/0")
|
||||
value = s.read()
|
||||
if value is None:
|
||||
print ("# %s = ? (failed to read from device)" % s.name)
|
||||
else:
|
||||
print (s.name, "=", value)
|
||||
return
|
||||
|
||||
setting = None
|
||||
for s in dev.settings:
|
||||
if args.setting.lower() == s.name.lower():
|
||||
setting = s
|
||||
break
|
||||
if setting is None:
|
||||
_fail("no setting '%s' for %s" % (args.setting, dev.name))
|
||||
|
||||
if args.value is None:
|
||||
result = setting.read()
|
||||
if result is None:
|
||||
_fail("failed to read '%s'" % setting.name)
|
||||
print ("%s = %s" % (setting.name, setting.read()))
|
||||
return
|
||||
|
||||
from logitech_receiver import settings as _settings
|
||||
|
||||
if setting.kind == _settings.KIND.toggle:
|
||||
value = args.value
|
||||
try:
|
||||
value = bool(int(value))
|
||||
except:
|
||||
if value.lower() in ('1', 'true', 'yes', 'on', 't', 'y'):
|
||||
value = True
|
||||
elif value.lower() in ('0', 'false', 'no', 'off', 'f', 'n'):
|
||||
value = False
|
||||
else:
|
||||
_fail("don't know how to interpret '%s' as boolean" % value)
|
||||
|
||||
elif setting.choices:
|
||||
value = args.value.lower()
|
||||
|
||||
if value in ('higher', 'lower'):
|
||||
old_value = setting.read()
|
||||
if old_value is None:
|
||||
_fail("could not read current value of '%s'" % setting.name)
|
||||
|
||||
if value == 'lower':
|
||||
lower_values = setting.choices[:old_value]
|
||||
value = lower_values[-1] if lower_values else setting.choices[:][0]
|
||||
elif value == 'higher':
|
||||
higher_values = setting.choices[old_value + 1:]
|
||||
value = higher_values[0] if higher_values else setting.choices[:][-1]
|
||||
elif value in ('highest', 'max'):
|
||||
value = setting.choices[:][-1]
|
||||
elif value in ('lowest', 'min'):
|
||||
value = setting.choices[:][0]
|
||||
elif value not in setting.choices:
|
||||
_fail("possible values for '%s' are: [%s]" % (setting.name, ', '.join(str(v) for v in setting.choices)))
|
||||
value = setting.choices[value]
|
||||
|
||||
else:
|
||||
raise NotImplemented
|
||||
|
||||
result = setting.write(value)
|
||||
if result is None:
|
||||
_fail("failed to set '%s' = '%s' [%r]" % (setting.name, value, value))
|
||||
print ("%s = %s" % (setting.name, result))
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def _parse_arguments():
|
||||
from argparse import ArgumentParser
|
||||
arg_parser = ArgumentParser(prog=NAME.lower())
|
||||
arg_parser.add_argument('-d', '--debug', action='count', default=0,
|
||||
help='print logging messages, for debugging purposes (may be repeated for extra verbosity)')
|
||||
arg_parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__)
|
||||
arg_parser.add_argument('-D', '--hidraw', action='store', dest='hidraw_path', metavar='PATH',
|
||||
help='unifying receiver to use; the first detected receiver if unspecified. Example: /dev/hidraw2')
|
||||
|
||||
subparsers = arg_parser.add_subparsers(title='commands')
|
||||
|
||||
sp = subparsers.add_parser('show', help='show information about paired devices')
|
||||
sp.add_argument('device', nargs='?', default='all',
|
||||
help='device to show information about; may be a device number (1..6), a device serial, '
|
||||
'at least 3 characters of a device\'s name, "receiver", or "all" (the default)')
|
||||
sp.add_argument('-v', '--verbose', action='store_true',
|
||||
help='print all available information about the inspected device(s)')
|
||||
sp.set_defaults(cmd=show_devices)
|
||||
|
||||
sp = subparsers.add_parser('config', help='read/write device-specific settings',
|
||||
epilog='Please note that configuration only works on active devices.')
|
||||
sp.add_argument('device',
|
||||
help='device to configure; may be a device number (1..6), a device serial, '
|
||||
'or at least 3 characters of a device\'s name')
|
||||
sp.add_argument('setting', nargs='?',
|
||||
help='device-specific setting; leave empty to list available settings')
|
||||
sp.add_argument('value', nargs='?',
|
||||
help='new value for the setting')
|
||||
sp.set_defaults(cmd=config_device)
|
||||
|
||||
sp = subparsers.add_parser('pair', help='pair a new device',
|
||||
epilog='The Logitech Unifying Receiver supports up to 6 paired devices at the same time.')
|
||||
sp.set_defaults(cmd=pair_device)
|
||||
|
||||
sp = subparsers.add_parser('unpair', help='unpair a device')
|
||||
sp.add_argument('device',
|
||||
help='device to unpair; may be a device number (1..6), a device serial, '
|
||||
'or at least 3 characters of a device\'s name.')
|
||||
sp.set_defaults(cmd=unpair_device)
|
||||
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
# Python 3 has an undocumented 'feature' that breaks parsing empty args
|
||||
# http://bugs.python.org/issue16308
|
||||
if not 'cmd' in args:
|
||||
arg_parser.print_usage(sys.stderr)
|
||||
sys.stderr.write('%s: error: too few arguments\n' % NAME.lower())
|
||||
sys.exit(2)
|
||||
|
||||
if args.debug > 0:
|
||||
log_level = logging.WARNING - 10 * args.debug
|
||||
log_format='%(asctime)s,%(msecs)03d %(levelname)8s %(name)s: %(message)s'
|
||||
logging.basicConfig(level=max(log_level, logging.DEBUG), format=log_format, datefmt='%H:%M:%S')
|
||||
else:
|
||||
logging.root.addHandler(logging.NullHandler())
|
||||
logging.root.setLevel(logging.ERROR)
|
||||
|
||||
return args
|
||||
|
||||
|
||||
def main():
|
||||
_require('pyudev', 'python-pyudev')
|
||||
args = _parse_arguments()
|
||||
receiver = _receiver(args.hidraw_path)
|
||||
args.cmd(receiver, args)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -0,0 +1,154 @@
|
|||
# -*- python-mode -*-
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
## Copyright (C) 2012-2013 Daniel Pavel
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
|
||||
import argparse as _argparse
|
||||
import sys as _sys
|
||||
|
||||
from logging import getLogger, DEBUG as _DEBUG
|
||||
_log = getLogger(__name__)
|
||||
del getLogger
|
||||
|
||||
|
||||
from solaar import NAME
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def _create_parser():
|
||||
parser = _argparse.ArgumentParser(prog=NAME.lower(), add_help=False,
|
||||
epilog='For details on individual actions, run `%s <action> --help`.' % NAME.lower())
|
||||
subparsers = parser.add_subparsers(title='actions',
|
||||
help='optional action to perform')
|
||||
|
||||
sp = subparsers.add_parser('show', help='show information about devices')
|
||||
sp.add_argument('device', nargs='?', default='all',
|
||||
help='device to show information about; may be a device number (1..6), a serial, '
|
||||
'a substring of a device\'s name, or "all" (the default)')
|
||||
sp.set_defaults(action='show')
|
||||
|
||||
sp = subparsers.add_parser('config', help='read/write device-specific settings',
|
||||
epilog='Please note that configuration only works on active devices.')
|
||||
sp.add_argument('device',
|
||||
help='device to configure; may be a device number (1..6), a device serial, '
|
||||
'or at least 3 characters of a device\'s name')
|
||||
sp.add_argument('setting', nargs='?',
|
||||
help='device-specific setting; leave empty to list available settings')
|
||||
sp.add_argument('value', nargs='?',
|
||||
help='new value for the setting')
|
||||
sp.set_defaults(action='config')
|
||||
|
||||
sp = subparsers.add_parser('pair', help='pair a new device',
|
||||
epilog='The Logitech Unifying Receiver supports up to 6 paired devices at the same time.')
|
||||
sp.add_argument('receiver', nargs='?',
|
||||
help='select a certain receiver when more than one is present')
|
||||
sp.set_defaults(action='pair')
|
||||
|
||||
sp = subparsers.add_parser('unpair', help='unpair a device')
|
||||
sp.add_argument('device',
|
||||
help='device to unpair; may be a device number (1..6), a serial, '
|
||||
'or a substring of a device\'s name.')
|
||||
sp.set_defaults(action='unpair')
|
||||
|
||||
return parser, subparsers.choices
|
||||
|
||||
|
||||
_cli_parser, actions = _create_parser()
|
||||
|
||||
|
||||
def _receivers():
|
||||
from logitech_receiver import Receiver
|
||||
from logitech_receiver.base import receivers
|
||||
for dev_info in receivers():
|
||||
try:
|
||||
r = Receiver.open(dev_info)
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("[%s] => %s", dev_info.path, r)
|
||||
if r:
|
||||
yield r
|
||||
except Exception as e:
|
||||
_log.exception('opening ' + str(dev_info))
|
||||
_sys.exit("%s: error: %s" % (NAME, str(e)))
|
||||
|
||||
|
||||
def _find_receiver(receivers, name):
|
||||
assert receivers
|
||||
assert name
|
||||
|
||||
for r in receivers:
|
||||
if name in r.name.lower() or name == r.serial.lower():
|
||||
return r
|
||||
|
||||
|
||||
def _find_device(receivers, name):
|
||||
assert receivers
|
||||
assert name
|
||||
|
||||
number = None
|
||||
if len(name) == 1:
|
||||
try:
|
||||
number = int(name)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
assert not (number < 0)
|
||||
if number > 6: number = None
|
||||
|
||||
for r in receivers:
|
||||
if number and number <= r.max_devices:
|
||||
dev = r[number]
|
||||
if dev:
|
||||
return dev
|
||||
|
||||
for dev in r:
|
||||
if (name == dev.serial.lower() or
|
||||
name == dev.codename.lower() or
|
||||
name == str(dev.kind).lower() or
|
||||
name in dev.name.lower()):
|
||||
return dev
|
||||
|
||||
raise Exception("no device found matching '%s'" % name)
|
||||
|
||||
|
||||
def run(cli_args=None):
|
||||
if cli_args == 'help':
|
||||
_cli_parser.print_help()
|
||||
return
|
||||
|
||||
if cli_args:
|
||||
action = cli_args[0]
|
||||
args = _cli_parser.parse_args(cli_args)
|
||||
else:
|
||||
args = _cli_parser.parse_args()
|
||||
action = args.action
|
||||
assert action in actions
|
||||
|
||||
try:
|
||||
c = list(_receivers())
|
||||
if not c:
|
||||
raise Exception('Logitech receiver not found')
|
||||
|
||||
from importlib import import_module
|
||||
m = import_module('.' + action, package=__name__)
|
||||
m.run(c, args, _find_receiver, _find_device)
|
||||
except Exception as e:
|
||||
_sys.exit('%s: error: %s' % (NAME.lower(), e))
|
|
@ -0,0 +1,120 @@
|
|||
# -*- python-mode -*-
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
## Copyright (C) 2012-2013 Daniel Pavel
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
|
||||
from solaar import configuration as _configuration
|
||||
from logitech_receiver import settings as _settings
|
||||
|
||||
|
||||
def _print_setting(s, verbose=True):
|
||||
print ('#', s.label)
|
||||
if verbose:
|
||||
print ('#', s.description.replace('\n', ' '))
|
||||
if s.kind == _settings.KIND.toggle:
|
||||
print ('# possible values: on/true/t/yes/y/1 or off/false/f/no/n/0')
|
||||
elif s.choices:
|
||||
print ('# possible values: one of [', ', '.join(str(v) for v in s.choices), '], or higher/lower/highest/max/lowest/min')
|
||||
else:
|
||||
# wtf?
|
||||
pass
|
||||
value = s.read(cached=False)
|
||||
if value is None:
|
||||
print (s.name, '= ? (failed to read from device)')
|
||||
else:
|
||||
print (s.name, '= %r' % value)
|
||||
|
||||
|
||||
def run(receivers, args, find_receiver, find_device):
|
||||
assert receivers
|
||||
assert args.device
|
||||
|
||||
device_name = args.device.lower()
|
||||
dev = find_device(receivers, device_name)
|
||||
|
||||
if not dev.ping():
|
||||
raise Exception('%s is offline' % dev.name)
|
||||
|
||||
if not dev.settings:
|
||||
raise Exception('no settings for %s' % dev.name)
|
||||
|
||||
_configuration.attach_to(dev)
|
||||
|
||||
if not args.setting:
|
||||
print (dev.name, '(%s) [%s:%s]' % (dev.codename, dev.wpid, dev.serial))
|
||||
for s in dev.settings:
|
||||
print ('')
|
||||
_print_setting(s)
|
||||
return
|
||||
|
||||
setting_name = args.setting.lower()
|
||||
setting = None
|
||||
for s in dev.settings:
|
||||
if setting_name == s.name.lower():
|
||||
setting = s
|
||||
break
|
||||
if setting is None:
|
||||
raise Exception("no setting '%s' for %s" % (args.setting, dev.name))
|
||||
|
||||
if args.value is None:
|
||||
_print_setting(setting)
|
||||
return
|
||||
|
||||
if setting.kind == _settings.KIND.toggle:
|
||||
value = args.value
|
||||
try:
|
||||
value = bool(int(value))
|
||||
except:
|
||||
if value.lower() in ('true', 'yes', 'on', 't', 'y'):
|
||||
value = True
|
||||
elif value.lower() in ('false', 'no', 'off', 'f', 'n'):
|
||||
value = False
|
||||
else:
|
||||
raise Exception("don't know how to interpret '%s' as boolean" % value)
|
||||
|
||||
elif setting.choices:
|
||||
value = args.value.lower()
|
||||
|
||||
if value in ('higher', 'lower'):
|
||||
old_value = setting.read()
|
||||
if old_value is None:
|
||||
raise Exception("could not read current value of '%s'" % setting.name)
|
||||
|
||||
if value == 'lower':
|
||||
lower_values = setting.choices[:old_value]
|
||||
value = lower_values[-1] if lower_values else setting.choices[:][0]
|
||||
elif value == 'higher':
|
||||
higher_values = setting.choices[old_value + 1:]
|
||||
value = higher_values[0] if higher_values else setting.choices[:][-1]
|
||||
elif value in ('highest', 'max'):
|
||||
value = setting.choices[:][-1]
|
||||
elif value in ('lowest', 'min'):
|
||||
value = setting.choices[:][0]
|
||||
elif value not in setting.choices:
|
||||
raise Exception("possible values for '%s' are: [%s]" % (setting.name, ', '.join(str(v) for v in setting.choices)))
|
||||
value = setting.choices[value]
|
||||
|
||||
else:
|
||||
raise NotImplemented
|
||||
|
||||
result = setting.write(value)
|
||||
if result is None:
|
||||
raise Exception("failed to set '%s' = '%s' [%r]" % (setting.name, value, value))
|
||||
_print_setting(setting, False)
|
|
@ -0,0 +1,91 @@
|
|||
# -*- python-mode -*-
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
## Copyright (C) 2012-2013 Daniel Pavel
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
|
||||
from time import time as _timestamp
|
||||
|
||||
from logitech_receiver import (
|
||||
base as _base,
|
||||
hidpp10 as _hidpp10,
|
||||
status as _status,
|
||||
notifications as _notifications,
|
||||
)
|
||||
|
||||
|
||||
def run(receivers, args, find_receiver, _ignore):
|
||||
assert receivers
|
||||
|
||||
if args.receiver:
|
||||
receiver_name = args.receiver.lower()
|
||||
receiver = find_receiver(receiver_name)
|
||||
if not receiver:
|
||||
raise Exception("no receiver found matching '%s'" % receiver_name)
|
||||
else:
|
||||
receiver = receivers[0]
|
||||
|
||||
assert receiver
|
||||
receiver.status = _status.ReceiverStatus(receiver, lambda *args, **kwargs: None)
|
||||
|
||||
# check if it's necessary to set the notification flags
|
||||
old_notification_flags = _hidpp10.get_notification_flags(receiver) or 0
|
||||
if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless):
|
||||
_hidpp10.set_notification_flags(receiver, old_notification_flags | _hidpp10.NOTIFICATION_FLAG.wireless)
|
||||
|
||||
# get all current devices
|
||||
known_devices = [dev.number for dev in receiver]
|
||||
|
||||
class _HandleWithNotificationHook(int):
|
||||
def notifications_hook(self, n):
|
||||
assert n
|
||||
if n.devnumber == 0xFF:
|
||||
_notifications.process(receiver, n)
|
||||
elif n.sub_id == 0x41 and n.address == 0x04:
|
||||
if n.devnumber not in known_devices:
|
||||
receiver.status.new_device = receiver[n.devnumber]
|
||||
|
||||
timeout = 20 # seconds
|
||||
receiver.handle = _HandleWithNotificationHook(receiver.handle)
|
||||
|
||||
receiver.set_lock(False, timeout=timeout)
|
||||
print ('Pairing: turn your new device on (timing out in', timeout, 'seconds).')
|
||||
|
||||
# the lock-open notification may come slightly later, wait for it a bit
|
||||
pairing_start = _timestamp()
|
||||
patience = 5 # seconds
|
||||
|
||||
while receiver.status.lock_open or _timestamp() - pairing_start < patience:
|
||||
n = _base.read(receiver.handle)
|
||||
if n:
|
||||
n = _base.make_notification(*n)
|
||||
if n:
|
||||
receiver.handle.notifications_hook(n)
|
||||
|
||||
if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless):
|
||||
# only clear the flags if they weren't set before, otherwise a
|
||||
# concurrently running Solaar app might stop working properly
|
||||
_hidpp10.set_notification_flags(receiver, old_notification_flags)
|
||||
|
||||
if receiver.status.new_device:
|
||||
dev = receiver.status.new_device
|
||||
print ('Paired device %d: %s (%s) [%s:%s]' % (dev.number, dev.name, dev.codename, dev.wpid, dev.serial))
|
||||
else:
|
||||
error = receiver.status.get(_status.KEYS.ERROR) or 'no device detected?'
|
||||
raise Exception("pairing failed: %s" % error)
|
|
@ -0,0 +1,146 @@
|
|||
# -*- python-mode -*-
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
## Copyright (C) 2012-2013 Daniel Pavel
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
|
||||
from logitech_receiver import (
|
||||
hidpp10 as _hidpp10,
|
||||
hidpp20 as _hidpp20,
|
||||
special_keys as _special_keys,
|
||||
)
|
||||
|
||||
|
||||
def _print_receiver(receiver):
|
||||
paired_count = receiver.count()
|
||||
|
||||
print ('Unifying Receiver')
|
||||
print (' Device path :', receiver.path)
|
||||
print (' USB id : 046d:%s' % receiver.product_id)
|
||||
print (' Serial :', receiver.serial)
|
||||
for f in receiver.firmware:
|
||||
print (' %-11s: %s' % (f.kind, f.version))
|
||||
|
||||
print (' Has', paired_count, 'paired device(s) out of a maximum of %d.' % receiver.max_devices)
|
||||
|
||||
notification_flags = _hidpp10.get_notification_flags(receiver)
|
||||
if notification_flags is not None:
|
||||
if notification_flags:
|
||||
notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
||||
print (' Notifications: %s (0x%06X)' % (', '.join(notification_names), notification_flags))
|
||||
else:
|
||||
print (' Notifications: (none)')
|
||||
|
||||
activity = receiver.read_register(_hidpp10.REGISTERS.devices_activity)
|
||||
if activity:
|
||||
activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)]
|
||||
activity_text = ', '.join(('%d=%d' % (d, a)) for d, a in activity if a > 0)
|
||||
print (' Device activity counters:', activity_text or '(empty)')
|
||||
|
||||
|
||||
def _print_device(dev):
|
||||
assert dev
|
||||
# check if the device is online
|
||||
dev.ping()
|
||||
|
||||
print (' %d: %s' % (dev.number, dev.name))
|
||||
print (' Codename :', dev.codename)
|
||||
print (' Kind :', dev.kind)
|
||||
print (' Wireless PID :', dev.wpid)
|
||||
if dev.protocol:
|
||||
print (' Protocol : HID++ %1.1f' % dev.protocol)
|
||||
else:
|
||||
print (' Protocol : unknown (device is offline)')
|
||||
if dev.polling_rate:
|
||||
print (' Polling rate :', dev.polling_rate, 'ms (%dHz)' % (1000 // dev.polling_rate))
|
||||
print (' Serial number:', dev.serial)
|
||||
for fw in dev.firmware:
|
||||
print (' %11s:' % fw.kind, (fw.name + ' ' + fw.version).strip())
|
||||
|
||||
if dev.power_switch_location:
|
||||
print (' The power switch is located on the %s.' % dev.power_switch_location)
|
||||
|
||||
if dev.online:
|
||||
notification_flags = _hidpp10.get_notification_flags(dev)
|
||||
if notification_flags is not None:
|
||||
if notification_flags:
|
||||
notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
||||
print (' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags))
|
||||
else:
|
||||
print (' Notifications: (none).')
|
||||
|
||||
if dev.online and dev.features:
|
||||
print (' Supports %d HID++ 2.0 features:' % len(dev.features))
|
||||
for index, feature in enumerate(dev.features):
|
||||
feature = dev.features[index]
|
||||
flags = dev.request(0x0000, feature.bytes(2))
|
||||
flags = 0 if flags is None else ord(flags[1:2])
|
||||
flags = _hidpp20.FEATURE_FLAG.flag_names(flags)
|
||||
print (' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags)))
|
||||
|
||||
if dev.online and dev.keys:
|
||||
print (' Has %d reprogrammable keys:' % len(dev.keys))
|
||||
for k in dev.keys:
|
||||
flags = _special_keys.KEY_FLAG.flag_names(k.flags)
|
||||
print (' %2d: %-26s => %-27s %s' % (k.index, k.key, k.task, ', '.join(flags)))
|
||||
|
||||
if dev.online:
|
||||
battery = _hidpp20.get_battery(dev)
|
||||
if battery is None:
|
||||
battery = _hidpp10.get_battery(dev)
|
||||
if battery is not None:
|
||||
from logitech_receiver.common import NamedInt as _NamedInt
|
||||
level, status = battery
|
||||
if isinstance(level, _NamedInt):
|
||||
text = str(level)
|
||||
else:
|
||||
text = '%d%%' % level
|
||||
print (' Battery: %s, %s.' % (text, status))
|
||||
else:
|
||||
print (' Battery status unavailable.')
|
||||
else:
|
||||
print (' Battery: unknown (device is offline).')
|
||||
|
||||
|
||||
def run(receivers, args, find_receiver, find_device):
|
||||
assert receivers
|
||||
assert args.device
|
||||
|
||||
device_name = args.device.lower()
|
||||
|
||||
if device_name == 'all':
|
||||
for r in receivers:
|
||||
_print_receiver(r)
|
||||
count = r.count()
|
||||
for dev in r:
|
||||
print ('')
|
||||
_print_device(dev)
|
||||
count -= 1
|
||||
if count == 0:
|
||||
break
|
||||
return
|
||||
|
||||
dev = find_receiver(receivers, device_name)
|
||||
if dev:
|
||||
_print_receiver(dev)
|
||||
return
|
||||
|
||||
dev = find_device(receivers, device_name)
|
||||
assert dev
|
||||
_print_device(dev)
|
|
@ -0,0 +1,36 @@
|
|||
# -*- python-mode -*-
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
## Copyright (C) 2012-2013 Daniel Pavel
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
|
||||
def run(receivers, args, find_receiver, find_device):
|
||||
assert receivers
|
||||
assert args.device
|
||||
|
||||
device_name = args.device.lower()
|
||||
dev = find_device(receivers, device_name)
|
||||
|
||||
# query these now, it's last chance to get them
|
||||
try:
|
||||
number, codename, wpid, serial = dev.number, dev.codename, dev.wpid, dev.serial
|
||||
del dev.receiver[number]
|
||||
print ('Unpaired %d: %s (%s) [%s:%s]' % (number, dev.name, codename, wpid, serial))
|
||||
except Exception as e:
|
||||
raise Exception('failed to unpair device %s: %s' % (dev.name, e))
|
|
@ -23,6 +23,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
|
|||
|
||||
from solaar import __version__, NAME
|
||||
import solaar.i18n as _i18n
|
||||
import solaar.cli as _cli
|
||||
|
||||
#
|
||||
#
|
||||
|
@ -40,10 +41,18 @@ def _parse_arguments():
|
|||
import argparse
|
||||
arg_parser = argparse.ArgumentParser(prog=NAME.lower())
|
||||
arg_parser.add_argument('-d', '--debug', action='count', default=0,
|
||||
help="print logging messages, for debugging purposes (may be repeated for extra verbosity)")
|
||||
help='print logging messages, for debugging purposes (may be repeated for extra verbosity)')
|
||||
arg_parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__)
|
||||
arg_parser.add_argument('--help-actions', action='store_true',
|
||||
help='print help for the optional actions')
|
||||
arg_parser.add_argument('action', nargs=argparse.REMAINDER, choices=_cli.actions,
|
||||
help='optional actions to perform')
|
||||
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
if args.help_actions:
|
||||
return 'help'
|
||||
|
||||
import logging
|
||||
if args.debug > 0:
|
||||
log_level = logging.WARNING - 10 * args.debug
|
||||
|
@ -53,34 +62,33 @@ def _parse_arguments():
|
|||
logging.root.addHandler(logging.NullHandler())
|
||||
logging.root.setLevel(logging.ERROR)
|
||||
|
||||
if args.action:
|
||||
return args.action
|
||||
|
||||
if logging.root.isEnabledFor(logging.INFO):
|
||||
logging.info("language %s (%s), translations path %s", _i18n.language, _i18n.encoding, _i18n.path)
|
||||
|
||||
return args
|
||||
|
||||
|
||||
def main():
|
||||
_require('pyudev', 'python-pyudev')
|
||||
_require('gi.repository', 'python-gi')
|
||||
_require('gi.repository.Gtk', 'gir1.2-gtk-3.0')
|
||||
_parse_arguments()
|
||||
|
||||
# handle ^C in console
|
||||
import signal
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
cli_action = _parse_arguments()
|
||||
if cli_action:
|
||||
return _cli.run(cli_action)
|
||||
|
||||
_require('gi.repository', 'python-gi')
|
||||
_require('gi.repository.Gtk', 'gir1.2-gtk-3.0')
|
||||
|
||||
try:
|
||||
import solaar.ui as ui
|
||||
ui.init()
|
||||
|
||||
import solaar.listener as listener
|
||||
listener.setup_scanner(ui.status_changed, ui.error_dialog)
|
||||
listener.start_all()
|
||||
|
||||
# main UI event loop
|
||||
ui.run_loop()
|
||||
|
||||
listener.stop_all()
|
||||
ui.run_loop(listener.start_all, listener.stop_all)
|
||||
except Exception as e:
|
||||
import sys
|
||||
sys.exit('%s: error: %s' % (NAME.lower(), e))
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
|
||||
from logging import getLogger, DEBUG as _DEBUG, INFO as _INFO
|
||||
from logging import getLogger, DEBUG as _DEBUG
|
||||
_log = getLogger(__name__)
|
||||
del getLogger
|
||||
|
||||
|
@ -37,27 +37,6 @@ assert Gtk.get_major_version() > 2, 'Solaar requires Gtk 3 python bindings'
|
|||
|
||||
GLib.threads_init()
|
||||
|
||||
def _init_application():
|
||||
APP_ID = 'io.github.pwr.solaar'
|
||||
app = Gtk.Application.new(APP_ID, 0)
|
||||
# not sure this is necessary...
|
||||
# app.set_property('register-session', True)
|
||||
registered = app.register(None)
|
||||
dbus_path = app.get_dbus_object_path() if hasattr(app, 'get_dbus_object_path') else APP_ID
|
||||
if _log.isEnabledFor(_INFO):
|
||||
_log.info("application %s, registered %s", dbus_path, registered)
|
||||
# assert registered, "failed to register unique application %s" % app
|
||||
|
||||
# if there is already a running instance, bail out
|
||||
if app.get_is_remote():
|
||||
# pop up the window in the other instance
|
||||
app.activate()
|
||||
raise Exception("already running")
|
||||
|
||||
return app
|
||||
|
||||
application = _init_application()
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
@ -72,7 +51,7 @@ def _error_dialog(reason, object):
|
|||
_("If you've just installed Solaar, try removing the receiver and plugging it back in.")
|
||||
elif reason == 'unpair':
|
||||
title = _("Unpairing failed")
|
||||
text = _("Failed to unpair %s from %s.") % (object.name, object.receiver.name) + \
|
||||
text = _("Failed to unpair %{device} from %{receiver}.").format(device=object.name, receiver=object.receiver.name) + \
|
||||
'\n\n' + \
|
||||
_("The receiver returned an error, with no further details.")
|
||||
else:
|
||||
|
@ -92,40 +71,13 @@ def error_dialog(reason, object):
|
|||
GLib.idle_add(_error_dialog, reason, object)
|
||||
|
||||
#
|
||||
# A separate thread is used to read/write from the device
|
||||
# so as not to block the main (GUI) thread.
|
||||
#
|
||||
#
|
||||
|
||||
try:
|
||||
from Queue import Queue
|
||||
except ImportError:
|
||||
from queue import Queue
|
||||
_task_queue = Queue(16)
|
||||
del Queue
|
||||
|
||||
|
||||
from threading import Thread, current_thread as _current_thread
|
||||
|
||||
def _process_async_queue():
|
||||
t = _current_thread()
|
||||
t.alive = True
|
||||
while t.alive:
|
||||
function, args, kwargs = _task_queue.get()
|
||||
if function:
|
||||
function(*args, **kwargs)
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("stopped")
|
||||
|
||||
_queue_processor = Thread(name='AsyncUI', target=_process_async_queue)
|
||||
_queue_processor.daemon = True
|
||||
_queue_processor.alive = False
|
||||
_queue_processor.start()
|
||||
|
||||
del Thread
|
||||
|
||||
_task_runner = None
|
||||
def async(function, *args, **kwargs):
|
||||
task = (function, args, kwargs)
|
||||
_task_queue.put(task)
|
||||
if _task_runner:
|
||||
_task_runner(function, *args, **kwargs)
|
||||
|
||||
#
|
||||
#
|
||||
|
@ -133,36 +85,73 @@ def async(function, *args, **kwargs):
|
|||
|
||||
from . import notify, tray, window
|
||||
|
||||
def init():
|
||||
|
||||
def _startup(app, startup_hook):
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("startup registered=%s, remote=%s", app.get_is_registered(), app.get_is_remote())
|
||||
|
||||
from solaar.async import TaskRunner as _TaskRunner
|
||||
global _task_runner
|
||||
_task_runner = _TaskRunner('AsyncUI')
|
||||
_task_runner.start()
|
||||
|
||||
notify.init()
|
||||
tray.init(lambda _ignore: window.destroy())
|
||||
window.init()
|
||||
|
||||
def run_loop():
|
||||
def _activate(app):
|
||||
assert app == application
|
||||
if app.get_windows():
|
||||
window.popup()
|
||||
else:
|
||||
app.add_window(window._window)
|
||||
startup_hook()
|
||||
|
||||
def _shutdown(app):
|
||||
# stop the async UI processor
|
||||
_queue_processor.alive = False
|
||||
async(None)
|
||||
|
||||
tray.destroy()
|
||||
notify.uninit()
|
||||
def _activate(app):
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("activate")
|
||||
if app.get_windows():
|
||||
window.popup()
|
||||
else:
|
||||
app.add_window(window._window)
|
||||
|
||||
|
||||
def _command_line(app, command_line):
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("command_line %s", command_line.get_arguments())
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def _shutdown(app, shutdown_hook):
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("shutdown")
|
||||
|
||||
shutdown_hook()
|
||||
|
||||
# stop the async UI processor
|
||||
global _task_runner
|
||||
_task_runner.stop()
|
||||
_task_runner = None
|
||||
|
||||
tray.destroy()
|
||||
notify.uninit()
|
||||
|
||||
|
||||
def run_loop(startup_hook, shutdown_hook, args=None):
|
||||
# from gi.repository.Gio import ApplicationFlags as _ApplicationFlags
|
||||
APP_ID = 'io.github.pwr.solaar'
|
||||
application = Gtk.Application.new(APP_ID, 0) # _ApplicationFlags.HANDLES_COMMAND_LINE)
|
||||
|
||||
application.connect('startup', _startup, startup_hook)
|
||||
application.connect('command-line', _command_line)
|
||||
application.connect('activate', _activate)
|
||||
application.connect('shutdown', _shutdown)
|
||||
application.run(None)
|
||||
application.connect('shutdown', _shutdown, shutdown_hook)
|
||||
|
||||
application.run(args)
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
from logitech_receiver.status import ALERT
|
||||
|
||||
|
||||
def _status_changed(device, alert, reason):
|
||||
assert device is not None
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
|
|
|
@ -65,8 +65,10 @@ def _create():
|
|||
logging.exception("failed to fully create the about dialog")
|
||||
|
||||
about.set_translator_credits('\n'.join((
|
||||
'Papoteur, David Geiger, Damien Lallement (français)',
|
||||
'Adrian Piotrowicz (polski)',
|
||||
'Daniel Pavel (română)',
|
||||
'Daniel Zippert, Emelie Snecker (svensk)',
|
||||
)))
|
||||
|
||||
about.set_website('http://pwr.github.io/Solaar/')
|
||||
|
|
|
@ -69,29 +69,41 @@ def _look_for_application_icons():
|
|||
del _environ
|
||||
# del _path
|
||||
|
||||
_default_theme = Gtk.IconTheme.get_default()
|
||||
for p in _look_for_application_icons():
|
||||
_default_theme.prepend_search_path(p)
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("icon theme paths: %s", _default_theme.get_search_path())
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
_default_theme = None
|
||||
_has_gpm_icons = None
|
||||
_has_oxygen_icons = None
|
||||
_has_gnome_icons = None
|
||||
_has_elementary_icons = None
|
||||
|
||||
_has_gpm_icons = _default_theme.has_icon('gpm-battery-020-charging')
|
||||
_has_oxygen_icons = _default_theme.has_icon('battery-charging-caution') and \
|
||||
_default_theme.has_icon('battery-charging-040')
|
||||
_has_gnome_icons = _default_theme.has_icon('battery-caution-charging') and \
|
||||
_default_theme.has_icon('battery-full-charged')
|
||||
_has_elementary_icons = _default_theme.has_icon('battery-020-charging')
|
||||
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("detected icon sets: gpm %s, oxygen %s, gnome %s, elementary %s",
|
||||
_has_gpm_icons, _has_oxygen_icons, _has_gnome_icons, _has_elementary_icons)
|
||||
if (not _has_gpm_icons and not _has_oxygen_icons and
|
||||
not _has_gnome_icons and not _has_elementary_icons):
|
||||
_log.warning("failed to detect a known icon set")
|
||||
def _init_icon_paths():
|
||||
global _default_theme
|
||||
if _default_theme:
|
||||
return
|
||||
|
||||
_default_theme = Gtk.IconTheme.get_default()
|
||||
for p in _look_for_application_icons():
|
||||
_default_theme.prepend_search_path(p)
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("icon theme paths: %s", _default_theme.get_search_path())
|
||||
|
||||
global _has_gpm_icons, _has_oxygen_icons, _has_gnome_icons, _has_elementary_icons
|
||||
|
||||
_has_gpm_icons = _default_theme.has_icon('gpm-battery-020-charging')
|
||||
_has_oxygen_icons = _default_theme.has_icon('battery-charging-caution') and \
|
||||
_default_theme.has_icon('battery-charging-040')
|
||||
_has_gnome_icons = _default_theme.has_icon('battery-caution-charging') and \
|
||||
_default_theme.has_icon('battery-full-charged')
|
||||
_has_elementary_icons = _default_theme.has_icon('battery-020-charging')
|
||||
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("detected icon sets: gpm %s, oxygen %s, gnome %s, elementary %s",
|
||||
_has_gpm_icons, _has_oxygen_icons, _has_gnome_icons, _has_elementary_icons)
|
||||
|
||||
if (not _has_gpm_icons and not _has_oxygen_icons and
|
||||
not _has_gnome_icons and not _has_elementary_icons):
|
||||
_log.warning("failed to detect a known icon set")
|
||||
|
||||
#
|
||||
#
|
||||
|
@ -106,6 +118,8 @@ def battery(level=None, charging=False):
|
|||
return icon_name
|
||||
|
||||
def _battery_icon_name(level, charging):
|
||||
_init_icon_paths()
|
||||
|
||||
if level is None or level < 0:
|
||||
return 'gpm-battery-missing' \
|
||||
if _has_gpm_icons and _default_theme.has_icon('gpm-battery-missing') \
|
||||
|
@ -186,6 +200,8 @@ def device_icon_set(name='_', kind=None):
|
|||
|
||||
|
||||
def device_icon_file(name, kind=None, size=_LARGE_SIZE):
|
||||
_init_icon_paths()
|
||||
|
||||
icon_set = device_icon_set(name, kind)
|
||||
assert icon_set
|
||||
for n in reversed(icon_set.names):
|
||||
|
@ -194,6 +210,8 @@ def device_icon_file(name, kind=None, size=_LARGE_SIZE):
|
|||
|
||||
|
||||
def device_icon_name(name, kind=None):
|
||||
_init_icon_paths()
|
||||
|
||||
icon_set = device_icon_set(name, kind)
|
||||
assert icon_set
|
||||
for n in reversed(icon_set.names):
|
||||
|
@ -202,6 +220,8 @@ def device_icon_name(name, kind=None):
|
|||
|
||||
|
||||
def icon_file(name, size=_LARGE_SIZE):
|
||||
_init_icon_paths()
|
||||
|
||||
if _default_theme.has_icon(name):
|
||||
theme_icon = _default_theme.lookup_icon(name, size, 0)
|
||||
file_name = theme_icon.get_filename()
|
||||
|
|
|
@ -112,8 +112,14 @@ try:
|
|||
if n is None:
|
||||
n = _notifications[summary] = Notify.Notification()
|
||||
|
||||
message = reason or (_("unpaired") if dev.status is None else
|
||||
(str(dev.status) or (_("connected") if dev.status else _("offline"))))
|
||||
if reason:
|
||||
message = reason
|
||||
elif dev.status is None:
|
||||
message = _("unpaired")
|
||||
elif bool(dev.status):
|
||||
message = dev.status.__str__() or _("connected")
|
||||
else:
|
||||
message = _("offline")
|
||||
|
||||
# we need to use the filename here because the notifications daemon
|
||||
# is an external application that does not know about our icon sets
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from logging import getLogger, DEBUG as _DEBUG, INFO as _INFO
|
||||
from logging import getLogger, DEBUG as _DEBUG
|
||||
_log = getLogger(__name__)
|
||||
del getLogger
|
||||
|
||||
|
@ -67,82 +67,88 @@ def _create_menu(quit_handler):
|
|||
return menu
|
||||
|
||||
|
||||
_last_scroll = 0
|
||||
def _scroll(tray_icon, event, direction=None):
|
||||
if direction is None:
|
||||
direction = event.direction
|
||||
now = event.time / 1000.0
|
||||
else:
|
||||
now = None
|
||||
|
||||
if direction != ScrollDirection.UP and direction != ScrollDirection.DOWN:
|
||||
# ignore all other directions
|
||||
return
|
||||
|
||||
if len(_devices_info) < 4:
|
||||
# don't bother with scrolling when there's only one receiver
|
||||
# with only one device (3 = [receiver, device, separator])
|
||||
return
|
||||
|
||||
# scroll events come way too fast (at least 5-6 at once)
|
||||
# so take a little break between them
|
||||
global _last_scroll
|
||||
now = now or _timestamp()
|
||||
if now - _last_scroll < 0.33: # seconds
|
||||
return
|
||||
_last_scroll = now
|
||||
|
||||
# if _log.isEnabledFor(_DEBUG):
|
||||
# _log.debug("scroll direction %s", direction)
|
||||
|
||||
global _picked_device
|
||||
candidate = None
|
||||
|
||||
if _picked_device is None:
|
||||
for info in _devices_info:
|
||||
# pick first peripheral found
|
||||
if info[1] is not None:
|
||||
candidate = info
|
||||
break
|
||||
else:
|
||||
found = False
|
||||
for info in _devices_info:
|
||||
if not info[1]:
|
||||
# only conside peripherals
|
||||
continue
|
||||
# compare peripherals
|
||||
if info[0:2] == _picked_device[0:2]:
|
||||
if direction == ScrollDirection.UP and candidate:
|
||||
# select previous device
|
||||
break
|
||||
found = True
|
||||
else:
|
||||
if found:
|
||||
candidate = info
|
||||
if direction == ScrollDirection.DOWN:
|
||||
break
|
||||
# if direction is up, but no candidate found before _picked,
|
||||
# let it run through all candidates, will get stuck with the last one
|
||||
else:
|
||||
if direction == ScrollDirection.DOWN:
|
||||
# only use the first one, in case no candidates are after _picked
|
||||
if candidate is None:
|
||||
candidate = info
|
||||
else:
|
||||
candidate = info
|
||||
|
||||
# if the last _picked_device is gone, clear it
|
||||
# the candidate will be either the first or last one remaining,
|
||||
# depending on the scroll direction
|
||||
if not found:
|
||||
_picked_device = None
|
||||
|
||||
_picked_device = candidate or _picked_device
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("scroll: picked %s", _picked_device)
|
||||
_update_tray_icon()
|
||||
|
||||
|
||||
try:
|
||||
# raise ImportError
|
||||
from gi.repository import AppIndicator3
|
||||
|
||||
if _log.isEnabledFor(_INFO):
|
||||
_log.info("using AppIndicator3")
|
||||
|
||||
_last_scroll = 0
|
||||
def _scroll(ind, _ignore, direction):
|
||||
if direction != ScrollDirection.UP and direction != ScrollDirection.DOWN:
|
||||
# ignore all other directions
|
||||
return
|
||||
|
||||
if len(_devices_info) < 4:
|
||||
# don't bother with scrolling when there's only one receiver
|
||||
# with only one device (3 = [receiver, device, separator])
|
||||
return
|
||||
|
||||
# scroll events come way too fast (at least 5-6 at once)
|
||||
# so take a little break between them
|
||||
global _last_scroll
|
||||
now = _timestamp()
|
||||
if now - _last_scroll < 0.33: # seconds
|
||||
return
|
||||
_last_scroll = now
|
||||
|
||||
# if _log.isEnabledFor(_DEBUG):
|
||||
# _log.debug("scroll direction %s", direction)
|
||||
|
||||
global _picked_device
|
||||
candidate = None
|
||||
|
||||
if _picked_device is None:
|
||||
for info in _devices_info:
|
||||
# pick first peripheral found
|
||||
if info[1] is not None:
|
||||
candidate = info
|
||||
break
|
||||
else:
|
||||
found = False
|
||||
for info in _devices_info:
|
||||
if not info[1]:
|
||||
# only conside peripherals
|
||||
continue
|
||||
# compare peripherals
|
||||
if info[0:2] == _picked_device[0:2]:
|
||||
if direction == ScrollDirection.UP and candidate:
|
||||
# select previous device
|
||||
break
|
||||
found = True
|
||||
else:
|
||||
if found:
|
||||
candidate = info
|
||||
if direction == ScrollDirection.DOWN:
|
||||
break
|
||||
# if direction is up, but no candidate found before _picked,
|
||||
# let it run through all candidates, will get stuck with the last one
|
||||
else:
|
||||
if direction == ScrollDirection.DOWN:
|
||||
# only use the first one, in case no candidates are after _picked
|
||||
if candidate is None:
|
||||
candidate = info
|
||||
else:
|
||||
candidate = info
|
||||
|
||||
# if the last _picked_device is gone, clear it
|
||||
# the candidate will be either the first or last one remaining,
|
||||
# depending on the scroll direction
|
||||
if not found:
|
||||
_picked_device = None
|
||||
|
||||
_picked_device = candidate or _picked_device
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("scroll: picked %s", _picked_device)
|
||||
_update_tray_icon()
|
||||
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("using AppIndicator3")
|
||||
|
||||
def _create(menu):
|
||||
theme_paths = Gtk.IconTheme.get_default().get_search_path()
|
||||
|
@ -201,8 +207,8 @@ try:
|
|||
|
||||
except ImportError:
|
||||
|
||||
if _log.isEnabledFor(_INFO):
|
||||
_log.info("using StatusIcon")
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("using StatusIcon")
|
||||
|
||||
def _create(menu):
|
||||
icon = Gtk.StatusIcon.new_from_icon_name(_icons.TRAY_INIT)
|
||||
|
@ -210,10 +216,9 @@ except ImportError:
|
|||
icon.set_title(NAME)
|
||||
icon.set_tooltip_text(NAME)
|
||||
icon.connect('activate', _window_toggle)
|
||||
|
||||
icon.connect('popup_menu',
|
||||
lambda icon, button, time:
|
||||
menu.popup(None, None, icon.position_menu, icon, button, time))
|
||||
icon.connect('scroll-event', _scroll)
|
||||
icon.connect('popup-menu',
|
||||
lambda icon, button, time: menu.popup(None, None, icon.position_menu, icon, button, time))
|
||||
|
||||
return icon
|
||||
|
||||
|
@ -506,7 +511,7 @@ def update(device=None):
|
|||
menu_items[no_receivers_index + 1].set_visible(not _devices_info)
|
||||
|
||||
global _picked_device
|
||||
if not _picked_device and device is not None and device.kind is not None:
|
||||
if (not _picked_device or _last_scroll == 0) and device is not None and device.kind is not None:
|
||||
# if it's just a receiver update, it's unlikely the picked device would change
|
||||
_picked_device = _pick_device_with_lowest_battery()
|
||||
|
||||
|
|
|
@ -76,9 +76,6 @@ _NANO_RECEIVER_TEXT = (
|
|||
# create UI layout
|
||||
#
|
||||
|
||||
Gtk.Window.set_default_icon_name(NAME.lower())
|
||||
Gtk.Window.set_default_icon_from_file(_icons.icon_file(NAME.lower()))
|
||||
|
||||
def _new_button(label, icon_name=None, icon_size=_NORMAL_BUTTON_ICON_SIZE, tooltip=None, toggle=False, clicked=None):
|
||||
if toggle:
|
||||
b = Gtk.ToggleButton()
|
||||
|
@ -630,7 +627,7 @@ def _update_device_panel(device, panel, buttons, full=False):
|
|||
panel._battery._icon.set_sensitive(True)
|
||||
|
||||
if isinstance(battery_level, _NamedInt):
|
||||
text = str(battery_level)
|
||||
text = _(str(battery_level))
|
||||
else:
|
||||
text = '%d%%' % battery_level
|
||||
if is_online:
|
||||
|
@ -734,6 +731,9 @@ _window = None
|
|||
|
||||
|
||||
def init():
|
||||
Gtk.Window.set_default_icon_name(NAME.lower())
|
||||
Gtk.Window.set_default_icon_from_file(_icons.icon_file(NAME.lower()))
|
||||
|
||||
global _model, _tree, _details, _info, _empty, _window
|
||||
_model = Gtk.TreeStore(*_COLUMN_TYPES)
|
||||
_tree = _create_tree(_model)
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
solaar (0.9.2-2) unstable; urgency=low
|
||||
|
||||
* Fixes for lintian warnings.
|
||||
|
||||
-- Daniel Pavel <daniel.pavel+debian@gmail.com> Wed, 24 Jul 2013 21:47:17 +0200
|
||||
|
||||
solaar (0.9.2-1) unstable; urgency=low
|
||||
|
||||
* Release 0.9.2.
|
||||
* Closes: #717766.
|
||||
|
||||
-- Daniel Pavel <daniel.pavel+debian@gmail.com> Wed, 24 Jul 2013 20:59:52 +0200
|
||||
|
||||
solaar (0.9.1-1) unstable; urgency=low
|
||||
|
||||
* Release 0.9.1.
|
||||
|
|
|
@ -2,7 +2,7 @@ Source: solaar
|
|||
Section: misc
|
||||
Priority: optional
|
||||
Maintainer: Daniel Pavel <daniel.pavel@gmail.com>
|
||||
Build-Depends: debhelper (>= 8)
|
||||
Build-Depends: debhelper (>= 9)
|
||||
Build-Depends-Indep: python, po-debconf
|
||||
X-Python-Version: >= 2.7
|
||||
X-Python3-Version: >= 3.2
|
||||
|
|
|
@ -42,7 +42,6 @@ License: LGPL
|
|||
Files: share/icons/light_*.png
|
||||
Copyright: Oxygen Icons
|
||||
License: LGPL
|
||||
Comment: These files were copied from the Oxygen icon theme (weather-*).
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
|
@ -55,3 +54,4 @@ Comment: These files were copied from the Oxygen icon theme (weather-*).
|
|||
.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
Comment: These files were copied from the Oxygen icon theme (weather-*).
|
||||
|
|
|
@ -0,0 +1,453 @@
|
|||
# French translations for solaar package.
|
||||
# Copyright (C) 2013 THE solaar'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the solaar package.
|
||||
# Automatically generated, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: solaar 0.9.2\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-08-08 21:51+0200\n"
|
||||
"PO-Revision-Date: 2013-08-07 14:43+0200\n"
|
||||
"Last-Translator: Damien Lallement <dams@mageia.org>\n"
|
||||
"Language-Team: Language: fr\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38
|
||||
msgid "critical"
|
||||
msgstr "critique"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38
|
||||
msgid "empty"
|
||||
msgstr "vide"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38 lib/logitech_receiver/i18n.py:41
|
||||
msgid "full"
|
||||
msgstr "pleine"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38
|
||||
msgid "good"
|
||||
msgstr "bonne"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38
|
||||
msgid "low"
|
||||
msgstr "faible"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:41
|
||||
msgid "almost full"
|
||||
msgstr "presque pleine"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:41
|
||||
msgid "discharging"
|
||||
msgstr "En décharge"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:41
|
||||
msgid "recharging"
|
||||
msgstr "En charge"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:42
|
||||
msgid "invalid battery"
|
||||
msgstr "batterie invalide"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:42
|
||||
msgid "slow recharge"
|
||||
msgstr "recharge lente"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:42
|
||||
msgid "thermal error"
|
||||
msgstr "erreur thermique"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:45
|
||||
msgid "device not supported"
|
||||
msgstr "périphérique non pris en charge"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:45
|
||||
msgid "device timeout"
|
||||
msgstr "le périphérique ne répond pas"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:45
|
||||
msgid "sequence timeout"
|
||||
msgstr "dépassement de délai"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:45
|
||||
msgid "too many devices"
|
||||
msgstr "trop de périphériques"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48
|
||||
msgid "Bootloader"
|
||||
msgstr "Chargeur d'amorçage"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||
msgid "Firmware"
|
||||
msgstr "Micrologiciel"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48
|
||||
msgid "Hardware"
|
||||
msgstr "Matériel"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48
|
||||
msgid "Other"
|
||||
msgstr "Autre"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:67
|
||||
msgid "closed"
|
||||
msgstr "fermé"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:67
|
||||
msgid "open"
|
||||
msgstr "ouvert"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:67
|
||||
msgid "pairing lock is "
|
||||
msgstr "le verrou de jumelage est "
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||
msgid "unpaired"
|
||||
msgstr "non jumelé"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:192
|
||||
msgid "powered on"
|
||||
msgstr "sous tension"
|
||||
|
||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||
msgid "unknown"
|
||||
msgstr "inconnu"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:77
|
||||
msgid "Smooth Scrolling"
|
||||
msgstr "Défilement fluide"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:78
|
||||
msgid "High-sensitivity mode for vertical scroll with the wheel."
|
||||
msgstr "Mode haute sensibilité pour défilement vertical avec la molette."
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:79
|
||||
msgid "Side Scrolling"
|
||||
msgstr "Défilement latéral"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:80
|
||||
msgid "When disabled, pushing the wheel sideways sends custom button "
|
||||
"events\n"
|
||||
"instead of the standard side-scrolling events."
|
||||
msgstr "Lorsque désactivé, l'appui sur les côtés de la molette envoie des "
|
||||
"évènements\n"
|
||||
" de bouton personnalisés à la place des évènements standards de "
|
||||
"défilement latéral."
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:82
|
||||
msgid "Sensitivity (DPI)"
|
||||
msgstr "Sensibilité (DPI)"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:83
|
||||
msgid "Swap Fx function"
|
||||
msgstr "Fonction Swap Fx"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:84
|
||||
msgid "When set, the F1..F12 keys will activate their special function,\n"
|
||||
"and you must hold the FN key to activate their standard function."
|
||||
msgstr "Lorsque défini, les touches F1..F12 activeront leurs fonctions "
|
||||
"spéciales,\n"
|
||||
"et vous devez maintenir la touche FN pour activer leurs fonctions "
|
||||
"standards."
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:87
|
||||
msgid "When unset, the F1..F12 keys will activate their standard function,\n"
|
||||
"and you must hold the FN key to activate their special function."
|
||||
msgstr "Lorsque non défini, les touches F1..F12 activeront leurs fonctions "
|
||||
"standards,\n"
|
||||
"et vous devez maintenir la touche FN pour activer leurs fonctions "
|
||||
"spéciales."
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:89
|
||||
msgid "Hand Detection"
|
||||
msgstr "Détection manuelle"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:90
|
||||
msgid "Turn on illumination when the hands hover over the keyboard."
|
||||
msgstr "Allume l'éclairage lorsque les mains passent au-dessus du clavier."
|
||||
|
||||
#: lib/logitech_receiver/status.py:98
|
||||
msgid "No paired devices."
|
||||
msgstr "Aucun périphériques jumelés"
|
||||
|
||||
#: lib/logitech_receiver/status.py:99
|
||||
msgid "1 paired device."
|
||||
msgstr "1 périphérique jumelé."
|
||||
|
||||
#: lib/logitech_receiver/status.py:100
|
||||
msgid " paired devices."
|
||||
msgstr " périphériques jumelés."
|
||||
|
||||
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||
#: lib/solaar/ui/window.py:143
|
||||
msgid "Battery"
|
||||
msgstr "Batterie"
|
||||
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||
msgid "Lighting"
|
||||
msgstr "Éclairage"
|
||||
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||
msgid "lux"
|
||||
msgstr "lux"
|
||||
|
||||
#: lib/solaar/listener.py:95
|
||||
msgid "The receiver was unplugged."
|
||||
msgstr "Le récepteur a été débranché."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:48
|
||||
msgid "Permissions error"
|
||||
msgstr "Erreur de permissions"
|
||||
|
||||
#: lib/solaar/ui/__init__.py:49
|
||||
#, python-format
|
||||
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||
"it."
|
||||
msgstr "Trouvé un récepteur Logitech (%s), mais n'a pas eu l'autorisation de "
|
||||
"l'ouvrir."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:51
|
||||
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||
"plugging it back in."
|
||||
msgstr "Si vous venez juste d'installer Solaar, essayez de retirer le "
|
||||
"récepteur et de le rebrancher."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:53
|
||||
msgid "Unpairing failed"
|
||||
msgstr "La déconnexion a échoué"
|
||||
|
||||
#: lib/solaar/ui/__init__.py:54
|
||||
#, python-brace-format
|
||||
msgid "Failed to unpair %{device} from %{receiver}."
|
||||
msgstr "Impossible de dissocier %{device} de %{receiver}."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:56
|
||||
msgid "The receiver returned an error, with no further details."
|
||||
msgstr "Le récepteur a retourné une erreur, sans plus de détails."
|
||||
|
||||
#: lib/solaar/ui/about.py:39
|
||||
msgid "Shows status of devices connected\n"
|
||||
"through wireless Logitech receivers."
|
||||
msgstr "Affiche l'état des périphériques connectés\n"
|
||||
"à travers les récepteurs sans fil Logitech."
|
||||
|
||||
#: lib/solaar/ui/about.py:48
|
||||
msgid "GUI design"
|
||||
msgstr "Interface graphique"
|
||||
|
||||
#: lib/solaar/ui/about.py:49
|
||||
msgid "Testing"
|
||||
msgstr "Testeur"
|
||||
|
||||
#: lib/solaar/ui/about.py:54
|
||||
msgid "Logitech documentation"
|
||||
msgstr "Documentațion Logitech"
|
||||
|
||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||
msgid "About"
|
||||
msgstr "À propos de"
|
||||
|
||||
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||
#: lib/solaar/ui/window.py:203
|
||||
msgid "Unpair"
|
||||
msgstr "Déconnecter"
|
||||
|
||||
#: lib/solaar/ui/config_panel.py:97
|
||||
msgid "Working"
|
||||
msgstr "En fonctionnement"
|
||||
|
||||
#: lib/solaar/ui/config_panel.py:100
|
||||
msgid "Read/write operation failed."
|
||||
msgstr "Les opérations de lecture/écriture ont échoué."
|
||||
|
||||
#: lib/solaar/ui/notify.py:120
|
||||
msgid "connected"
|
||||
msgstr "connecté"
|
||||
|
||||
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||
msgid "offline"
|
||||
msgstr "non connecté"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:133
|
||||
msgid "Pairing failed"
|
||||
msgstr "Le jumelage a échoué"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:135
|
||||
msgid "Make sure your device is within range, and has a decent battery "
|
||||
"charge."
|
||||
msgstr "Assurez-vous que votre périphérique soit à portée, et que sa "
|
||||
"batterie soit suffisamment chargée."
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:137
|
||||
msgid "A new device was detected, but it is not compatible with this "
|
||||
"receiver."
|
||||
msgstr "Un nouveau périphérique a été détecté, mais il n'est pas compatible "
|
||||
"avec ce récepteur."
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:139
|
||||
#, python-format
|
||||
msgid "The receiver only supports %d paired device(s)."
|
||||
msgstr "Le récepteur supporte seulement %d périphérique(s). "
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:141
|
||||
msgid "No further details are available about the error."
|
||||
msgstr "Aucun autre détail n'est disponible à propos de l'erreur."
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:155
|
||||
msgid "Found a new device"
|
||||
msgstr "Nouveau périphérique disponible"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:180
|
||||
msgid "The wireless link is not encrypted"
|
||||
msgstr "La connexion sans fil n'est pas chiffrée"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:197
|
||||
msgid "pair new device"
|
||||
msgstr "Jumele le nouveau périphérique"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:205
|
||||
msgid "Turn on the device you want to pair."
|
||||
msgstr "Allumez le périphérique que vous souhaitez jumeler."
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:206
|
||||
msgid "If the device is already turned on,\n"
|
||||
"turn if off and on again."
|
||||
msgstr "Si le périphérique est déjà allumé,\n"
|
||||
"éteignez le et rallumez-le à nouveau."
|
||||
|
||||
#: lib/solaar/ui/tray.py:55
|
||||
msgid "No Logitech receiver found"
|
||||
msgstr "Aucun récepteur Logitech trouvé"
|
||||
|
||||
#: lib/solaar/ui/tray.py:62
|
||||
msgid "Quit"
|
||||
msgstr "Quitter"
|
||||
|
||||
#: lib/solaar/ui/tray.py:274
|
||||
msgid "no receiver"
|
||||
msgstr "aucun récepteur"
|
||||
|
||||
#: lib/solaar/ui/tray.py:293
|
||||
msgid "no status"
|
||||
msgstr "aucun statut"
|
||||
|
||||
#: lib/solaar/ui/window.py:58
|
||||
msgid "The wireless link between this device and its receiver is encrypted."
|
||||
msgstr "La connexion sans fil entre cet appareil et son récepteur est "
|
||||
"chiffrée."
|
||||
|
||||
#: lib/solaar/ui/window.py:59
|
||||
msgid "The wireless link between this device and its receiver is not "
|
||||
"encrypted.\n"
|
||||
"\n"
|
||||
"For pointing devices (mice, trackballs, trackpads), this is a minor "
|
||||
"security issue.\n"
|
||||
"\n"
|
||||
"It is, however, a major security issue for text-input devices "
|
||||
"(keyboards, numpads),\n"
|
||||
"because typed text can be sniffed inconspicuously by 3rd parties "
|
||||
"within range."
|
||||
msgstr "La connexion sans fil entre cet appareil et son récepteur n'est pas "
|
||||
"chiffrée.\n"
|
||||
"\n"
|
||||
"Pour des dispositifs de pointage (souris, trackball, trackpad), "
|
||||
"c'est une faille mineure de sécurité\n"
|
||||
"\n"
|
||||
"Par contre, c'est une faille majeure pour les dispositifs d'entrée "
|
||||
"de texte (clavier, pavé numérique)\n"
|
||||
"car les données saisies peuvent être volées à votre insu par des "
|
||||
"tiers à proximité."
|
||||
|
||||
#: lib/solaar/ui/window.py:67 lib/solaar/ui/window.py:71
|
||||
msgid "No device paired"
|
||||
msgstr "Aucun périphérique jumelé"
|
||||
|
||||
#: lib/solaar/ui/window.py:67 lib/solaar/ui/window.py:68
|
||||
#, python-format
|
||||
msgid "Up to %d devices can be paired to this receiver"
|
||||
msgstr "Jusqu'à %d périphériques peuvent être jumelés à ce récepteur"
|
||||
|
||||
#: lib/solaar/ui/window.py:68
|
||||
msgid "paired devices"
|
||||
msgstr "périphérique(s) jumelé(s)"
|
||||
|
||||
#: lib/solaar/ui/window.py:72
|
||||
msgid "Only one device can be paired to this receiver"
|
||||
msgstr "Un seul périphérique peut être jumelé à ce récepteur"
|
||||
|
||||
#: lib/solaar/ui/window.py:110
|
||||
msgid "Scanning"
|
||||
msgstr "Balayage"
|
||||
|
||||
#: lib/solaar/ui/window.py:146
|
||||
msgid "Wireless Link"
|
||||
msgstr "Connexion sans fil"
|
||||
|
||||
#: lib/solaar/ui/window.py:179
|
||||
msgid "Show Technical Details"
|
||||
msgstr "Voir les détails techniques"
|
||||
|
||||
#: lib/solaar/ui/window.py:192
|
||||
msgid "Pair new device"
|
||||
msgstr "Jumeler un nouveau périphérique"
|
||||
|
||||
#: lib/solaar/ui/window.py:211
|
||||
msgid "Select a device"
|
||||
msgstr "Sélectionner un périphérique"
|
||||
|
||||
#: lib/solaar/ui/window.py:508
|
||||
msgid "Path"
|
||||
msgstr "Chemin"
|
||||
|
||||
#: lib/solaar/ui/window.py:510
|
||||
msgid "USB id"
|
||||
msgstr "Id USB"
|
||||
|
||||
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||
msgid "Serial"
|
||||
msgstr "Numéro de série"
|
||||
|
||||
#: lib/solaar/ui/window.py:519
|
||||
msgid "Index"
|
||||
msgstr "Index"
|
||||
|
||||
#: lib/solaar/ui/window.py:520
|
||||
msgid "Wireless PID"
|
||||
msgstr "PID sans fil"
|
||||
|
||||
#: lib/solaar/ui/window.py:522
|
||||
msgid "Protocol"
|
||||
msgstr "Protocole"
|
||||
|
||||
#: lib/solaar/ui/window.py:524
|
||||
msgid "Polling rate"
|
||||
msgstr "Taux de scrutation"
|
||||
|
||||
#: lib/solaar/ui/window.py:539
|
||||
msgid "none"
|
||||
msgstr "aucun"
|
||||
|
||||
#: lib/solaar/ui/window.py:540
|
||||
msgid "Notifications"
|
||||
msgstr "Notifications"
|
||||
|
||||
#: lib/solaar/ui/window.py:635
|
||||
msgid "charging"
|
||||
msgstr "en charge"
|
||||
|
||||
#: lib/solaar/ui/window.py:637
|
||||
msgid "last known"
|
||||
msgstr "dernière valeur connue"
|
||||
|
||||
#: lib/solaar/ui/window.py:644
|
||||
msgid "not encrypted"
|
||||
msgstr "non chiffrée"
|
||||
|
||||
#: lib/solaar/ui/window.py:648
|
||||
msgid "encrypted"
|
||||
msgstr "chiffrée"
|
92
po/pl.po
92
po/pl.po
|
@ -6,7 +6,7 @@
|
|||
msgid ""
|
||||
msgstr "Project-Id-Version: solaar 0.9.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-07-23 22:38+0200\n"
|
||||
"POT-Creation-Date: 2013-08-08 21:53+0200\n"
|
||||
"PO-Revision-Date: 2013-07-23 10:41+0100\n"
|
||||
"Last-Translator: Adrian Piotrowicz <nexces@nxstudio.pl>\n"
|
||||
"Language-Team: none\n"
|
||||
|
@ -82,7 +82,7 @@ msgstr "za dużo urządzeń"
|
|||
msgid "Bootloader"
|
||||
msgstr "Bootloader"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:538
|
||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||
msgid "Firmware"
|
||||
msgstr "Firmware"
|
||||
|
||||
|
@ -106,11 +106,15 @@ msgstr "otwarte"
|
|||
msgid "pairing lock is "
|
||||
msgstr "blokada parowania jest"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||
msgid "unpaired"
|
||||
msgstr "nie sparowany"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:192
|
||||
msgid "powered on"
|
||||
msgstr "włączone"
|
||||
|
||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:625
|
||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||
msgid "unknown"
|
||||
msgstr "nieznane"
|
||||
|
||||
|
@ -177,16 +181,16 @@ msgstr "1 sparowane urządzenie."
|
|||
msgid " paired devices."
|
||||
msgstr "sparowane(-ych) urządzeń."
|
||||
|
||||
#: lib/logitech_receiver/status.py:153 lib/logitech_receiver/status.py:155
|
||||
#: lib/solaar/ui/window.py:146
|
||||
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||
#: lib/solaar/ui/window.py:143
|
||||
msgid "Battery"
|
||||
msgstr "Bateria"
|
||||
|
||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:153
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||
msgid "Lighting"
|
||||
msgstr "Podświetlenie"
|
||||
|
||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:666
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||
msgid "lux"
|
||||
msgstr "lux"
|
||||
|
||||
|
@ -194,33 +198,33 @@ msgstr "lux"
|
|||
msgid "The receiver was unplugged."
|
||||
msgstr "Odbiornik został odłączony."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:69
|
||||
#: lib/solaar/ui/__init__.py:48
|
||||
msgid "Permissions error"
|
||||
msgstr "Błąd uprawnień"
|
||||
|
||||
#: lib/solaar/ui/__init__.py:70
|
||||
#: lib/solaar/ui/__init__.py:49
|
||||
#, fuzzy, python-format
|
||||
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||
"it."
|
||||
msgstr "Znaleziono odbiornik Logitech (%s), ale nie ma uprawnień do "
|
||||
"otworzenia go."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:72
|
||||
#: lib/solaar/ui/__init__.py:51
|
||||
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||
"plugging it back in."
|
||||
msgstr "Jeżeli właśnie zainstalowałeś Solaar spróbuj odłączyć nadajnik i "
|
||||
"podłączyć go ponownie."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:74
|
||||
#: lib/solaar/ui/__init__.py:53
|
||||
msgid "Unpairing failed"
|
||||
msgstr "Usunięcie parowania nie powiodło się"
|
||||
|
||||
#: lib/solaar/ui/__init__.py:75
|
||||
#, python-format
|
||||
msgid "Failed to unpair %s from %s."
|
||||
msgstr "Nie powidło się usunięcie parowania %s z %s."
|
||||
#: lib/solaar/ui/__init__.py:54
|
||||
#, python-brace-format
|
||||
msgid "Failed to unpair %{device} from %{receiver}."
|
||||
msgstr "Nie powidło się usunięcie parowania %{device} z %{receiver}."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:77
|
||||
#: lib/solaar/ui/__init__.py:56
|
||||
msgid "The receiver returned an error, with no further details."
|
||||
msgstr "Odbiornik zwrócił błąd bez dodatkowych informacji."
|
||||
|
||||
|
@ -242,12 +246,12 @@ msgstr "Testy"
|
|||
msgid "Logitech documentation"
|
||||
msgstr "Dokumentacja Logitech"
|
||||
|
||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:319
|
||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||
msgid "About"
|
||||
msgstr "O"
|
||||
|
||||
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||
#: lib/solaar/ui/window.py:206
|
||||
#: lib/solaar/ui/window.py:203
|
||||
msgid "Unpair"
|
||||
msgstr "Usuń parowanie"
|
||||
|
||||
|
@ -259,16 +263,12 @@ msgstr "Pracuję"
|
|||
msgid "Read/write operation failed."
|
||||
msgstr "Operacja odczytu/zapisu nie powiodła się."
|
||||
|
||||
#: lib/solaar/ui/notify.py:115
|
||||
msgid "unpaired"
|
||||
msgstr "nie sparowany"
|
||||
|
||||
#: lib/solaar/ui/notify.py:116
|
||||
#: lib/solaar/ui/notify.py:120
|
||||
msgid "connected"
|
||||
msgstr "podłączony"
|
||||
|
||||
#: lib/solaar/ui/notify.py:116 lib/solaar/ui/tray.py:285
|
||||
#: lib/solaar/ui/tray.py:290 lib/solaar/ui/window.py:656
|
||||
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||
msgid "offline"
|
||||
msgstr "wyłączony"
|
||||
|
||||
|
@ -326,11 +326,11 @@ msgstr "Nie znaleziono odbiornika Logitech"
|
|||
msgid "Quit"
|
||||
msgstr "Wyjdź"
|
||||
|
||||
#: lib/solaar/ui/tray.py:269
|
||||
#: lib/solaar/ui/tray.py:274
|
||||
msgid "no receiver"
|
||||
msgstr "brak odbiornika"
|
||||
|
||||
#: lib/solaar/ui/tray.py:288
|
||||
#: lib/solaar/ui/tray.py:293
|
||||
msgid "no status"
|
||||
msgstr "brak statusu"
|
||||
|
||||
|
@ -380,75 +380,75 @@ msgstr "sparowane urządzenia"
|
|||
msgid "Only one device can be paired to this receiver"
|
||||
msgstr "Tylko jedno urządzenie może być sparowane z tym odbiornikiem"
|
||||
|
||||
#: lib/solaar/ui/window.py:113
|
||||
#: lib/solaar/ui/window.py:110
|
||||
msgid "Scanning"
|
||||
msgstr "Wyszukiwanie"
|
||||
|
||||
#: lib/solaar/ui/window.py:149
|
||||
#: lib/solaar/ui/window.py:146
|
||||
msgid "Wireless Link"
|
||||
msgstr "Połączenie bezprzewodowe"
|
||||
|
||||
#: lib/solaar/ui/window.py:182
|
||||
#: lib/solaar/ui/window.py:179
|
||||
msgid "Show Technical Details"
|
||||
msgstr "Wyświetl szczegóły techniczne"
|
||||
|
||||
#: lib/solaar/ui/window.py:195
|
||||
#: lib/solaar/ui/window.py:192
|
||||
msgid "Pair new device"
|
||||
msgstr "Sparuj nowe urządzenie"
|
||||
|
||||
#: lib/solaar/ui/window.py:214
|
||||
#: lib/solaar/ui/window.py:211
|
||||
msgid "Select a device"
|
||||
msgstr "Wybierz urządzenie"
|
||||
|
||||
#: lib/solaar/ui/window.py:511
|
||||
#: lib/solaar/ui/window.py:508
|
||||
msgid "Path"
|
||||
msgstr "Ścieżka"
|
||||
|
||||
#: lib/solaar/ui/window.py:513
|
||||
#: lib/solaar/ui/window.py:510
|
||||
msgid "USB id"
|
||||
msgstr "USB id"
|
||||
|
||||
#: lib/solaar/ui/window.py:516 lib/solaar/ui/window.py:518
|
||||
#: lib/solaar/ui/window.py:530 lib/solaar/ui/window.py:532
|
||||
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||
msgid "Serial"
|
||||
msgstr "Serial"
|
||||
|
||||
#: lib/solaar/ui/window.py:522
|
||||
#: lib/solaar/ui/window.py:519
|
||||
msgid "Index"
|
||||
msgstr "Index"
|
||||
|
||||
#: lib/solaar/ui/window.py:523
|
||||
#: lib/solaar/ui/window.py:520
|
||||
msgid "Wireless PID"
|
||||
msgstr "Wireless PID"
|
||||
|
||||
#: lib/solaar/ui/window.py:525
|
||||
#: lib/solaar/ui/window.py:522
|
||||
msgid "Protocol"
|
||||
msgstr "Protokół"
|
||||
|
||||
#: lib/solaar/ui/window.py:527
|
||||
#: lib/solaar/ui/window.py:524
|
||||
msgid "Polling rate"
|
||||
msgstr "Częstotliwość próbkowania"
|
||||
|
||||
#: lib/solaar/ui/window.py:542
|
||||
#: lib/solaar/ui/window.py:539
|
||||
msgid "none"
|
||||
msgstr "brak"
|
||||
|
||||
#: lib/solaar/ui/window.py:543
|
||||
#: lib/solaar/ui/window.py:540
|
||||
msgid "Notifications"
|
||||
msgstr "Powiadomienia"
|
||||
|
||||
#: lib/solaar/ui/window.py:638
|
||||
#: lib/solaar/ui/window.py:635
|
||||
msgid "charging"
|
||||
msgstr "ładowanie"
|
||||
|
||||
#: lib/solaar/ui/window.py:640
|
||||
#: lib/solaar/ui/window.py:637
|
||||
msgid "last known"
|
||||
msgstr "ostatni znany"
|
||||
|
||||
#: lib/solaar/ui/window.py:647
|
||||
#: lib/solaar/ui/window.py:644
|
||||
msgid "not encrypted"
|
||||
msgstr "nie szyfrowane"
|
||||
|
||||
#: lib/solaar/ui/window.py:651
|
||||
#: lib/solaar/ui/window.py:648
|
||||
msgid "encrypted"
|
||||
msgstr "szyfrowane"
|
||||
|
|
92
po/ro.po
92
po/ro.po
|
@ -6,7 +6,7 @@
|
|||
msgid ""
|
||||
msgstr "Project-Id-Version: solaar 0.9.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-07-23 22:35+0200\n"
|
||||
"POT-Creation-Date: 2013-08-08 21:53+0200\n"
|
||||
"PO-Revision-Date: 2013-07-17 20:27+0100\n"
|
||||
"Last-Translator: Daniel Pavel <daniel.pavel@gmail.com>\n"
|
||||
"Language-Team: none\n"
|
||||
|
@ -82,7 +82,7 @@ msgstr "prea multe periferice"
|
|||
msgid "Bootloader"
|
||||
msgstr ""
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:538
|
||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||
msgid "Firmware"
|
||||
msgstr ""
|
||||
|
||||
|
@ -106,11 +106,15 @@ msgstr "deschis"
|
|||
msgid "pairing lock is "
|
||||
msgstr "lacătul de contectare este "
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||
msgid "unpaired"
|
||||
msgstr "deconectat(ă)"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:192
|
||||
msgid "powered on"
|
||||
msgstr "a pornit"
|
||||
|
||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:625
|
||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||
msgid "unknown"
|
||||
msgstr "necunoscută"
|
||||
|
||||
|
@ -174,16 +178,16 @@ msgstr "Un periferic contectat."
|
|||
msgid " paired devices."
|
||||
msgstr " periferice contectate."
|
||||
|
||||
#: lib/logitech_receiver/status.py:153 lib/logitech_receiver/status.py:155
|
||||
#: lib/solaar/ui/window.py:146
|
||||
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||
#: lib/solaar/ui/window.py:143
|
||||
msgid "Battery"
|
||||
msgstr "Baterie"
|
||||
|
||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:153
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||
msgid "Lighting"
|
||||
msgstr "Lumină"
|
||||
|
||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:666
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||
msgid "lux"
|
||||
msgstr "lucși"
|
||||
|
||||
|
@ -191,32 +195,32 @@ msgstr "lucși"
|
|||
msgid "The receiver was unplugged."
|
||||
msgstr "Receptor deconectat."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:69
|
||||
#: lib/solaar/ui/__init__.py:48
|
||||
msgid "Permissions error"
|
||||
msgstr "Eroare de permisiuni"
|
||||
|
||||
#: lib/solaar/ui/__init__.py:70
|
||||
#: lib/solaar/ui/__init__.py:49
|
||||
#, python-format
|
||||
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||
"it."
|
||||
msgstr "Receptor Logitech detectat (%s), dar nu am permisiunea să-l deschid."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:72
|
||||
#: lib/solaar/ui/__init__.py:51
|
||||
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||
"plugging it back in."
|
||||
msgstr "Dacă tocmai ați instalat Solaar, scoateți receptorul și re-"
|
||||
"introduceți-l."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:74
|
||||
#: lib/solaar/ui/__init__.py:53
|
||||
msgid "Unpairing failed"
|
||||
msgstr "Deconectare eșuată"
|
||||
|
||||
#: lib/solaar/ui/__init__.py:75
|
||||
#, python-format
|
||||
msgid "Failed to unpair %s from %s."
|
||||
msgstr "Deconectarea %s de la %s a eșuat."
|
||||
#: lib/solaar/ui/__init__.py:54
|
||||
#, python-brace-format
|
||||
msgid "Failed to unpair %{device} from %{receiver}."
|
||||
msgstr "Deconectarea %{device} de la %{receiver} a eșuat."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:77
|
||||
#: lib/solaar/ui/__init__.py:56
|
||||
msgid "The receiver returned an error, with no further details."
|
||||
msgstr "Receptorul a semnalat o eroare, fără alte detalii."
|
||||
|
||||
|
@ -238,12 +242,12 @@ msgstr "Testare"
|
|||
msgid "Logitech documentation"
|
||||
msgstr "Documentație Logitech"
|
||||
|
||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:319
|
||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||
msgid "About"
|
||||
msgstr "Despre"
|
||||
|
||||
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||
#: lib/solaar/ui/window.py:206
|
||||
#: lib/solaar/ui/window.py:203
|
||||
msgid "Unpair"
|
||||
msgstr "Deconectează"
|
||||
|
||||
|
@ -255,16 +259,12 @@ msgstr "Prelucrez"
|
|||
msgid "Read/write operation failed."
|
||||
msgstr "Operațiunea a eșuat."
|
||||
|
||||
#: lib/solaar/ui/notify.py:115
|
||||
msgid "unpaired"
|
||||
msgstr "deconectat(ă)"
|
||||
|
||||
#: lib/solaar/ui/notify.py:116
|
||||
#: lib/solaar/ui/notify.py:120
|
||||
msgid "connected"
|
||||
msgstr "conectat(ă)"
|
||||
|
||||
#: lib/solaar/ui/notify.py:116 lib/solaar/ui/tray.py:285
|
||||
#: lib/solaar/ui/tray.py:290 lib/solaar/ui/window.py:656
|
||||
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||
msgid "offline"
|
||||
msgstr "inactivă"
|
||||
|
||||
|
@ -323,11 +323,11 @@ msgstr "Nu am găsit nici un receptor Logitech"
|
|||
msgid "Quit"
|
||||
msgstr "Ieșire"
|
||||
|
||||
#: lib/solaar/ui/tray.py:269
|
||||
#: lib/solaar/ui/tray.py:274
|
||||
msgid "no receiver"
|
||||
msgstr "nici un receptor"
|
||||
|
||||
#: lib/solaar/ui/tray.py:288
|
||||
#: lib/solaar/ui/tray.py:293
|
||||
msgid "no status"
|
||||
msgstr "stare necunoscută"
|
||||
|
||||
|
@ -365,75 +365,75 @@ msgstr "periferice conectate"
|
|||
msgid "Only one device can be paired to this receiver"
|
||||
msgstr "Acest receptor suportă un singur periferic conectat"
|
||||
|
||||
#: lib/solaar/ui/window.py:113
|
||||
#: lib/solaar/ui/window.py:110
|
||||
msgid "Scanning"
|
||||
msgstr "Caut"
|
||||
|
||||
#: lib/solaar/ui/window.py:149
|
||||
#: lib/solaar/ui/window.py:146
|
||||
msgid "Wireless Link"
|
||||
msgstr "Legatură fără fir"
|
||||
|
||||
#: lib/solaar/ui/window.py:182
|
||||
#: lib/solaar/ui/window.py:179
|
||||
msgid "Show Technical Details"
|
||||
msgstr "Detalii tehnice"
|
||||
|
||||
#: lib/solaar/ui/window.py:195
|
||||
#: lib/solaar/ui/window.py:192
|
||||
msgid "Pair new device"
|
||||
msgstr "Conectează periferic"
|
||||
|
||||
#: lib/solaar/ui/window.py:214
|
||||
#: lib/solaar/ui/window.py:211
|
||||
msgid "Select a device"
|
||||
msgstr "Selectați un dispozitiv"
|
||||
|
||||
#: lib/solaar/ui/window.py:511
|
||||
#: lib/solaar/ui/window.py:508
|
||||
msgid "Path"
|
||||
msgstr "Cale"
|
||||
|
||||
#: lib/solaar/ui/window.py:513
|
||||
#: lib/solaar/ui/window.py:510
|
||||
msgid "USB id"
|
||||
msgstr "USB"
|
||||
|
||||
#: lib/solaar/ui/window.py:516 lib/solaar/ui/window.py:518
|
||||
#: lib/solaar/ui/window.py:530 lib/solaar/ui/window.py:532
|
||||
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||
msgid "Serial"
|
||||
msgstr "Serial"
|
||||
|
||||
#: lib/solaar/ui/window.py:522
|
||||
#: lib/solaar/ui/window.py:519
|
||||
msgid "Index"
|
||||
msgstr "Index"
|
||||
|
||||
#: lib/solaar/ui/window.py:523
|
||||
#: lib/solaar/ui/window.py:520
|
||||
msgid "Wireless PID"
|
||||
msgstr "Cod WPID"
|
||||
|
||||
#: lib/solaar/ui/window.py:525
|
||||
#: lib/solaar/ui/window.py:522
|
||||
msgid "Protocol"
|
||||
msgstr "Protocol"
|
||||
|
||||
#: lib/solaar/ui/window.py:527
|
||||
#: lib/solaar/ui/window.py:524
|
||||
msgid "Polling rate"
|
||||
msgstr "Rată acces"
|
||||
|
||||
#: lib/solaar/ui/window.py:542
|
||||
#: lib/solaar/ui/window.py:539
|
||||
msgid "none"
|
||||
msgstr "nici una"
|
||||
|
||||
#: lib/solaar/ui/window.py:543
|
||||
#: lib/solaar/ui/window.py:540
|
||||
msgid "Notifications"
|
||||
msgstr "Notificări"
|
||||
|
||||
#: lib/solaar/ui/window.py:638
|
||||
#: lib/solaar/ui/window.py:635
|
||||
msgid "charging"
|
||||
msgstr "se încarcă"
|
||||
|
||||
#: lib/solaar/ui/window.py:640
|
||||
#: lib/solaar/ui/window.py:637
|
||||
msgid "last known"
|
||||
msgstr "ultima valoare"
|
||||
|
||||
#: lib/solaar/ui/window.py:647
|
||||
#: lib/solaar/ui/window.py:644
|
||||
msgid "not encrypted"
|
||||
msgstr "ne-criptată"
|
||||
|
||||
#: lib/solaar/ui/window.py:651
|
||||
#: lib/solaar/ui/window.py:648
|
||||
msgid "encrypted"
|
||||
msgstr "criptată"
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
msgid ""
|
||||
msgstr "Project-Id-Version: solaar 0.9.2\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
<<<<<<< HEAD
|
||||
"POT-Creation-Date: 2013-08-05 18:51+0300\n"
|
||||
=======
|
||||
"POT-Creation-Date: 2013-08-08 22:21+0200\n"
|
||||
>>>>>>> master
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -80,7 +84,7 @@ msgstr ""
|
|||
msgid "Bootloader"
|
||||
msgstr ""
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:538
|
||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||
msgid "Firmware"
|
||||
msgstr ""
|
||||
|
||||
|
@ -104,11 +108,15 @@ msgstr ""
|
|||
msgid "pairing lock is "
|
||||
msgstr ""
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||
msgid "unpaired"
|
||||
msgstr ""
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:192
|
||||
msgid "powered on"
|
||||
msgstr ""
|
||||
|
||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:625
|
||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
|
||||
|
@ -168,16 +176,16 @@ msgstr ""
|
|||
msgid " paired devices."
|
||||
msgstr ""
|
||||
|
||||
#: lib/logitech_receiver/status.py:153 lib/logitech_receiver/status.py:155
|
||||
#: lib/solaar/ui/window.py:146
|
||||
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||
#: lib/solaar/ui/window.py:143
|
||||
msgid "Battery"
|
||||
msgstr ""
|
||||
|
||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:153
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||
msgid "Lighting"
|
||||
msgstr ""
|
||||
|
||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:666
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||
msgid "lux"
|
||||
msgstr ""
|
||||
|
||||
|
@ -185,31 +193,31 @@ msgstr ""
|
|||
msgid "The receiver was unplugged."
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/__init__.py:69
|
||||
#: lib/solaar/ui/__init__.py:48
|
||||
msgid "Permissions error"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/__init__.py:70
|
||||
#: lib/solaar/ui/__init__.py:49
|
||||
#, python-format
|
||||
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||
"it."
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/__init__.py:72
|
||||
#: lib/solaar/ui/__init__.py:51
|
||||
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||
"plugging it back in."
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/__init__.py:74
|
||||
#: lib/solaar/ui/__init__.py:53
|
||||
msgid "Unpairing failed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/__init__.py:75
|
||||
#, python-format
|
||||
msgid "Failed to unpair %s from %s."
|
||||
#: lib/solaar/ui/__init__.py:54
|
||||
#, python-brace-format
|
||||
msgid "Failed to unpair %{device} from %{receiver}."
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/__init__.py:77
|
||||
#: lib/solaar/ui/__init__.py:56
|
||||
msgid "The receiver returned an error, with no further details."
|
||||
msgstr ""
|
||||
|
||||
|
@ -230,12 +238,12 @@ msgstr ""
|
|||
msgid "Logitech documentation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:319
|
||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||
msgid "About"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||
#: lib/solaar/ui/window.py:206
|
||||
#: lib/solaar/ui/window.py:203
|
||||
msgid "Unpair"
|
||||
msgstr ""
|
||||
|
||||
|
@ -247,16 +255,12 @@ msgstr ""
|
|||
msgid "Read/write operation failed."
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/notify.py:115
|
||||
msgid "unpaired"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/notify.py:116
|
||||
#: lib/solaar/ui/notify.py:120
|
||||
msgid "connected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/notify.py:116 lib/solaar/ui/tray.py:285
|
||||
#: lib/solaar/ui/tray.py:290 lib/solaar/ui/window.py:656
|
||||
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||
msgid "offline"
|
||||
msgstr ""
|
||||
|
||||
|
@ -312,11 +316,11 @@ msgstr ""
|
|||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/tray.py:269
|
||||
#: lib/solaar/ui/tray.py:274
|
||||
msgid "no receiver"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/tray.py:288
|
||||
#: lib/solaar/ui/tray.py:293
|
||||
msgid "no status"
|
||||
msgstr ""
|
||||
|
||||
|
@ -354,75 +358,75 @@ msgstr ""
|
|||
msgid "Only one device can be paired to this receiver"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:113
|
||||
#: lib/solaar/ui/window.py:110
|
||||
msgid "Scanning"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:149
|
||||
#: lib/solaar/ui/window.py:146
|
||||
msgid "Wireless Link"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:182
|
||||
#: lib/solaar/ui/window.py:179
|
||||
msgid "Show Technical Details"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:195
|
||||
#: lib/solaar/ui/window.py:192
|
||||
msgid "Pair new device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:214
|
||||
#: lib/solaar/ui/window.py:211
|
||||
msgid "Select a device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:511
|
||||
#: lib/solaar/ui/window.py:508
|
||||
msgid "Path"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:513
|
||||
#: lib/solaar/ui/window.py:510
|
||||
msgid "USB id"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:516 lib/solaar/ui/window.py:518
|
||||
#: lib/solaar/ui/window.py:530 lib/solaar/ui/window.py:532
|
||||
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||
msgid "Serial"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:522
|
||||
#: lib/solaar/ui/window.py:519
|
||||
msgid "Index"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:523
|
||||
#: lib/solaar/ui/window.py:520
|
||||
msgid "Wireless PID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:525
|
||||
#: lib/solaar/ui/window.py:522
|
||||
msgid "Protocol"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:527
|
||||
#: lib/solaar/ui/window.py:524
|
||||
msgid "Polling rate"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:542
|
||||
#: lib/solaar/ui/window.py:539
|
||||
msgid "none"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:543
|
||||
#: lib/solaar/ui/window.py:540
|
||||
msgid "Notifications"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:638
|
||||
#: lib/solaar/ui/window.py:635
|
||||
msgid "charging"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:640
|
||||
#: lib/solaar/ui/window.py:637
|
||||
msgid "last known"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:647
|
||||
#: lib/solaar/ui/window.py:644
|
||||
msgid "not encrypted"
|
||||
msgstr ""
|
||||
|
||||
#: lib/solaar/ui/window.py:651
|
||||
#: lib/solaar/ui/window.py:648
|
||||
msgid "encrypted"
|
||||
msgstr ""
|
||||
|
|
|
@ -0,0 +1,451 @@
|
|||
# Swedish translations for solaar package.
|
||||
# Copyright (C) 2013 THE solaar'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the solaar package.
|
||||
# Automatically generated, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: solaar 0.9.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-08-08 19:46+0200\n"
|
||||
"PO-Revision-Date: 2013-07-27 16:28+0100\n"
|
||||
"Last-Translator: Daniel Zippert & Emelie Snecker <daniel@zippert."
|
||||
"se>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
"X-Poedit-Basepath: /pwr/Solaar/po\n"
|
||||
"X-Poedit-SearchPath-0: /pwr/Solaar/po\n"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38
|
||||
msgid "critical"
|
||||
msgstr "kritisk"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38
|
||||
msgid "empty"
|
||||
msgstr "tom"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38 lib/logitech_receiver/i18n.py:41
|
||||
msgid "full"
|
||||
msgstr "full"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38
|
||||
msgid "good"
|
||||
msgstr "normal"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:38
|
||||
msgid "low"
|
||||
msgstr "låg"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:41
|
||||
msgid "almost full"
|
||||
msgstr "nästan full"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:41
|
||||
msgid "discharging"
|
||||
msgstr "laddar ur"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:41
|
||||
msgid "recharging"
|
||||
msgstr "laddar"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:42
|
||||
msgid "invalid battery"
|
||||
msgstr "batterifel"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:42
|
||||
msgid "slow recharge"
|
||||
msgstr "långsam laddning"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:42
|
||||
msgid "thermal error"
|
||||
msgstr "termiskt fel"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:45
|
||||
msgid "device not supported"
|
||||
msgstr "enheten stöds inte"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:45
|
||||
msgid "device timeout"
|
||||
msgstr "enheten svarde inte i tid"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:45
|
||||
msgid "sequence timeout"
|
||||
msgstr "sekvens timout"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:45
|
||||
msgid "too many devices"
|
||||
msgstr "för många enheter"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48
|
||||
msgid "Bootloader"
|
||||
msgstr "Bootloader"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||
msgid "Firmware"
|
||||
msgstr "Firmware"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48
|
||||
msgid "Hardware"
|
||||
msgstr "Hårdvara"
|
||||
|
||||
#: lib/logitech_receiver/i18n.py:48
|
||||
msgid "Other"
|
||||
msgstr "Annan"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:67
|
||||
msgid "closed"
|
||||
msgstr "låst"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:67
|
||||
msgid "open"
|
||||
msgstr "öppen"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:67
|
||||
msgid "pairing lock is "
|
||||
msgstr "parkopplingsläge låst"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||
msgid "unpaired"
|
||||
msgstr "inte parkopplad"
|
||||
|
||||
#: lib/logitech_receiver/notifications.py:192
|
||||
msgid "powered on"
|
||||
msgstr "påslagen"
|
||||
|
||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||
msgid "unknown"
|
||||
msgstr "okänd"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:77
|
||||
msgid "Smooth Scrolling"
|
||||
msgstr "Mjuk Scrollning"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:78
|
||||
msgid "High-sensitivity mode for vertical scroll with the wheel."
|
||||
msgstr "Hög känslighet för scrollhjulet. "
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:79
|
||||
msgid "Side Scrolling"
|
||||
msgstr "Vertikal Scrollning"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:80
|
||||
msgid "When disabled, pushing the wheel sideways sends custom button "
|
||||
"events\n"
|
||||
"instead of the standard side-scrolling events."
|
||||
msgstr "Vid avaktivering, kommer tryckningar sidledes på scrollhjulet\n"
|
||||
"fungera som specialknappar istället för standard sidscrolling."
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:82
|
||||
msgid "Sensitivity (DPI)"
|
||||
msgstr "Känslighet (DPI)"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:83
|
||||
msgid "Swap Fx function"
|
||||
msgstr "Skifta funktionen för F1-12 tangenterna"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:84
|
||||
msgid "When set, the F1..F12 keys will activate their special function,\n"
|
||||
"and you must hold the FN key to activate their standard function."
|
||||
msgstr "Vid aktivering, kommer F1-12 tangenterna få sina specialfunktioner,\n"
|
||||
"och du behöver trycka ned FN tangenten för att komma åt dess normala "
|
||||
"funktioner."
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:87
|
||||
msgid "When unset, the F1..F12 keys will activate their standard function,\n"
|
||||
"and you must hold the FN key to activate their special function."
|
||||
msgstr "Vid avaktivering, kommer F1-12 tangenterna få sina "
|
||||
"standardfunktioner,\n"
|
||||
"och du behöver trycka ned FN tangenten för att komma åt dess "
|
||||
"spesicalfunktioner."
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:89
|
||||
msgid "Hand Detection"
|
||||
msgstr "Handavkänning"
|
||||
|
||||
#: lib/logitech_receiver/settings_templates.py:90
|
||||
msgid "Turn on illumination when the hands hover over the keyboard."
|
||||
msgstr "Tänd belysning, om en hand hålls över tangentbordet. "
|
||||
|
||||
#: lib/logitech_receiver/status.py:98
|
||||
msgid "No paired devices."
|
||||
msgstr "Inga enheter är parkopplade"
|
||||
|
||||
#: lib/logitech_receiver/status.py:99
|
||||
msgid "1 paired device."
|
||||
msgstr "1 parkopplad enhet."
|
||||
|
||||
#: lib/logitech_receiver/status.py:100
|
||||
msgid " paired devices."
|
||||
msgstr "parkopplade enheter."
|
||||
|
||||
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||
#: lib/solaar/ui/window.py:143
|
||||
msgid "Battery"
|
||||
msgstr "Batteri"
|
||||
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||
msgid "Lighting"
|
||||
msgstr "Belysning"
|
||||
|
||||
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||
msgid "lux"
|
||||
msgstr "lux"
|
||||
|
||||
#: lib/solaar/listener.py:95
|
||||
msgid "The receiver was unplugged."
|
||||
msgstr "Mottagaren kopplades ur"
|
||||
|
||||
#: lib/solaar/ui/__init__.py:48
|
||||
msgid "Permissions error"
|
||||
msgstr "Behörighetsfel"
|
||||
|
||||
#: lib/solaar/ui/__init__.py:49
|
||||
#, python-format
|
||||
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||
"it."
|
||||
msgstr "En Logitech mottagare hittades (%s), men behörighet att använda "
|
||||
"den saknas."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:51
|
||||
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||
"plugging it back in."
|
||||
msgstr "Om du just installerade solaar, prova koppla ur mottagaren och "
|
||||
"anslut den sedan igen. "
|
||||
|
||||
#: lib/solaar/ui/__init__.py:53
|
||||
msgid "Unpairing failed"
|
||||
msgstr "Kunde inte bryta parkoppling."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:54
|
||||
#, python-brace-format
|
||||
msgid "Failed to unpair %{device} from %{receiver}."
|
||||
msgstr "Misslyckades att bryta parkoppling mellan %{device} och %{receiver}."
|
||||
|
||||
#: lib/solaar/ui/__init__.py:56
|
||||
msgid "The receiver returned an error, with no further details."
|
||||
msgstr "Mottagaren rapporterade ett fel, utan specifika detaljer."
|
||||
|
||||
#: lib/solaar/ui/about.py:39
|
||||
msgid "Shows status of devices connected\n"
|
||||
"through wireless Logitech receivers."
|
||||
msgstr "Visa status för enheter kopplade till\n"
|
||||
"din trådlösa Logitech mottagare"
|
||||
|
||||
#: lib/solaar/ui/about.py:48
|
||||
msgid "GUI design"
|
||||
msgstr "GUI utseende"
|
||||
|
||||
#: lib/solaar/ui/about.py:49
|
||||
msgid "Testing"
|
||||
msgstr "Prövar"
|
||||
|
||||
#: lib/solaar/ui/about.py:54
|
||||
msgid "Logitech documentation"
|
||||
msgstr "Logitech dokumentation"
|
||||
|
||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||
msgid "About"
|
||||
msgstr "Om"
|
||||
|
||||
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||
#: lib/solaar/ui/window.py:203
|
||||
msgid "Unpair"
|
||||
msgstr "Ta bort parkoppling"
|
||||
|
||||
#: lib/solaar/ui/config_panel.py:97
|
||||
msgid "Working"
|
||||
msgstr "Lyckades"
|
||||
|
||||
#: lib/solaar/ui/config_panel.py:100
|
||||
msgid "Read/write operation failed."
|
||||
msgstr "Läsning/Skrivning misslyckades."
|
||||
|
||||
#: lib/solaar/ui/notify.py:120
|
||||
msgid "connected"
|
||||
msgstr "ansluten"
|
||||
|
||||
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||
msgid "offline"
|
||||
msgstr "avstängd"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:133
|
||||
msgid "Pairing failed"
|
||||
msgstr "Parkoppling misslyckades"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:135
|
||||
msgid "Make sure your device is within range, and has a decent battery "
|
||||
"charge."
|
||||
msgstr "Se till så att enheten inom räckhåll, och har tillräckligt laddat "
|
||||
"batteri. "
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:137
|
||||
msgid "A new device was detected, but it is not compatible with this "
|
||||
"receiver."
|
||||
msgstr "En ny enhet upptäcktes, men är inte kompatibel med mottagaren. "
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:139
|
||||
#, python-format
|
||||
msgid "The receiver only supports %d paired device(s)."
|
||||
msgstr "Mottagaren klarar bara %d parkopplad(e) enhet(er)."
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:141
|
||||
msgid "No further details are available about the error."
|
||||
msgstr "Ingen mer information är tillgänglig om felet. "
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:155
|
||||
msgid "Found a new device"
|
||||
msgstr "Ny enhet har hittats"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:180
|
||||
msgid "The wireless link is not encrypted"
|
||||
msgstr "Den trådlösa anslutningen är okrypterad"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:197
|
||||
msgid "pair new device"
|
||||
msgstr "parkoppla ny enhet"
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:205
|
||||
msgid "Turn on the device you want to pair."
|
||||
msgstr "Sätt på enheten du vill parkoppla."
|
||||
|
||||
#: lib/solaar/ui/pair_window.py:206
|
||||
msgid "If the device is already turned on,\n"
|
||||
"turn if off and on again."
|
||||
msgstr "Om enheten redan är igång,\n"
|
||||
"stäng av den och sätt på den igen."
|
||||
|
||||
#: lib/solaar/ui/tray.py:55
|
||||
msgid "No Logitech receiver found"
|
||||
msgstr "Ingen Logitech motagare hittades"
|
||||
|
||||
#: lib/solaar/ui/tray.py:62
|
||||
msgid "Quit"
|
||||
msgstr "Stäng"
|
||||
|
||||
#: lib/solaar/ui/tray.py:274
|
||||
msgid "no receiver"
|
||||
msgstr "ingen mottagare"
|
||||
|
||||
#: lib/solaar/ui/tray.py:293
|
||||
msgid "no status"
|
||||
msgstr "ingen status"
|
||||
|
||||
#: lib/solaar/ui/window.py:58
|
||||
msgid "The wireless link between this device and its receiver is encrypted."
|
||||
msgstr "Den trådlösa anslutningen är krypterad."
|
||||
|
||||
#: lib/solaar/ui/window.py:59
|
||||
msgid "The wireless link between this device and its receiver is not "
|
||||
"encrypted.\n"
|
||||
"\n"
|
||||
"For pointing devices (mice, trackballs, trackpads), this is a minor "
|
||||
"security issue.\n"
|
||||
"\n"
|
||||
"It is, however, a major security issue for text-input devices "
|
||||
"(keyboards, numpads),\n"
|
||||
"because typed text can be sniffed inconspicuously by 3rd parties "
|
||||
"within range."
|
||||
msgstr "Den trådlösa anslutningen mellan den här enheten och mottagaren är "
|
||||
"okrypterad\n"
|
||||
"\n"
|
||||
"For pekdon (möss, styrkulor, pekplattor), är detta inget stort "
|
||||
"säkerhetsproblem.\n"
|
||||
"\n"
|
||||
"Men för textinmatande enheter (tangentbord, numpads) är denna "
|
||||
"säkerhetsbrist allvarlig, eftersom skriven text obemärkt kan fångas "
|
||||
"upp av tredje part som befinner sig inom enhetens räckhåll. "
|
||||
|
||||
#: lib/solaar/ui/window.py:67 lib/solaar/ui/window.py:71
|
||||
msgid "No device paired"
|
||||
msgstr "Inga enheter parkopplade"
|
||||
|
||||
#: lib/solaar/ui/window.py:67 lib/solaar/ui/window.py:68
|
||||
#, python-format
|
||||
msgid "Up to %d devices can be paired to this receiver"
|
||||
msgstr "Upp till %d enheter kan parkopplas till mottagaren"
|
||||
|
||||
#: lib/solaar/ui/window.py:68
|
||||
msgid "paired devices"
|
||||
msgstr "parkopplade enheter"
|
||||
|
||||
#: lib/solaar/ui/window.py:72
|
||||
msgid "Only one device can be paired to this receiver"
|
||||
msgstr "Bara en enhet kan parkopplas till den här mottagaren"
|
||||
|
||||
#: lib/solaar/ui/window.py:110
|
||||
msgid "Scanning"
|
||||
msgstr "Söker"
|
||||
|
||||
#: lib/solaar/ui/window.py:146
|
||||
msgid "Wireless Link"
|
||||
msgstr "Trådlös anslutning"
|
||||
|
||||
#: lib/solaar/ui/window.py:179
|
||||
msgid "Show Technical Details"
|
||||
msgstr "Visa Tekniska Detaljer"
|
||||
|
||||
#: lib/solaar/ui/window.py:192
|
||||
msgid "Pair new device"
|
||||
msgstr "Parkoppla en ny enhet"
|
||||
|
||||
#: lib/solaar/ui/window.py:211
|
||||
msgid "Select a device"
|
||||
msgstr "Välj en enhet"
|
||||
|
||||
#: lib/solaar/ui/window.py:508
|
||||
msgid "Path"
|
||||
msgstr "Sökväg"
|
||||
|
||||
#: lib/solaar/ui/window.py:510
|
||||
msgid "USB id"
|
||||
msgstr "USB id"
|
||||
|
||||
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||
msgid "Serial"
|
||||
msgstr "Seriell"
|
||||
|
||||
#: lib/solaar/ui/window.py:519
|
||||
msgid "Index"
|
||||
msgstr "Index"
|
||||
|
||||
#: lib/solaar/ui/window.py:520
|
||||
msgid "Wireless PID"
|
||||
msgstr "Trådlös PID"
|
||||
|
||||
#: lib/solaar/ui/window.py:522
|
||||
msgid "Protocol"
|
||||
msgstr "Protokoll"
|
||||
|
||||
#: lib/solaar/ui/window.py:524
|
||||
msgid "Polling rate"
|
||||
msgstr "Uppdateringshastighet"
|
||||
|
||||
#: lib/solaar/ui/window.py:539
|
||||
msgid "none"
|
||||
msgstr "ingen"
|
||||
|
||||
#: lib/solaar/ui/window.py:540
|
||||
msgid "Notifications"
|
||||
msgstr "Notifikation "
|
||||
|
||||
#: lib/solaar/ui/window.py:635
|
||||
msgid "charging"
|
||||
msgstr "laddar"
|
||||
|
||||
#: lib/solaar/ui/window.py:637
|
||||
msgid "last known"
|
||||
msgstr "senast kända"
|
||||
|
||||
#: lib/solaar/ui/window.py:644
|
||||
msgid "not encrypted"
|
||||
msgstr "okrypterad"
|
||||
|
||||
#: lib/solaar/ui/window.py:648
|
||||
msgid "encrypted"
|
||||
msgstr "krypterad"
|
|
@ -80,8 +80,8 @@ done
|
|||
|
||||
# create packages/ sub-directory
|
||||
/bin/mkdir --parents "$SITE/../packages" "$SITE/packages/"
|
||||
/bin/cp --archive --update --target-directory="$SITE/../packages/" "$SELF/dist/debian"/solaar_* || true
|
||||
/bin/cp --archive --update --target-directory="$SITE/../packages/" "$SELF/dist/debian"/solaar-gnome3_* || true
|
||||
#/bin/cp --archive --update --target-directory="$SITE/../packages/" "$SELF/dist/debian"/solaar_* || true
|
||||
#/bin/cp --archive --update --target-directory="$SITE/../packages/" "$SELF/dist/debian"/solaar-gnome3_* || true
|
||||
if test -x /usr/bin/dpkg-scanpackages; then
|
||||
cd "$SITE/../packages/"
|
||||
/bin/rm --force *.build
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
#!/bin/sh
|
||||
|
||||
if test -z "$1"; then
|
||||
echo "Use: $0 <locale>"
|
||||
exit 2
|
||||
fi
|
||||
LL_CC="$1"
|
||||
shift
|
||||
|
||||
set -e
|
||||
|
||||
if test "$1" = "-h" -o "$1" = "--help"; then
|
||||
echo "Use: $0 [<language>]"
|
||||
echo "Run without arguments to update all translation files."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "$(readlink -f "$(dirname "$0")/..")"
|
||||
|
||||
VERSION=$(python setup.py --version)
|
||||
|
@ -33,18 +32,11 @@ POT_FILE="$POT_DIR/$DOMAIN.pot"
|
|||
|
||||
/bin/sed --in-place --expression="s/charset=CHARSET/charset=UTF-8/" "$POT_FILE"
|
||||
|
||||
PO_FILE="$POT_DIR/$LL_CC.po"
|
||||
|
||||
test -r "$PO_FILE" || /usr/bin/msginit \
|
||||
--no-translator --locale="$LL_CC" \
|
||||
--input="$POT_FILE" \
|
||||
--output-file="$PO_FILE"
|
||||
|
||||
unfmt() {
|
||||
local SOURCE="/usr/share/locale/$LL_CC/LC_MESSAGES/$1.mo"
|
||||
if [ ! -f $SOURCE ]
|
||||
then
|
||||
local SOURCE="/usr/share/locale-langpack/$LL_CC/LC_MESSAGES/$1.mo"
|
||||
if test ! -f "$SOURCE"; then
|
||||
SOURCE="/usr/share/locale-langpack/$LL_CC/LC_MESSAGES/$1.mo"
|
||||
fi
|
||||
local TARGET="$(mktemp --tmpdir $1-$LL_CC-XXXXXX.po)"
|
||||
/usr/bin/msgunfmt \
|
||||
|
@ -54,14 +46,32 @@ unfmt() {
|
|||
echo "$TARGET"
|
||||
}
|
||||
|
||||
/usr/bin/msgmerge \
|
||||
--update --no-fuzzy-matching \
|
||||
--no-escape --indent --add-location --sort-by-file \
|
||||
--lang="$LL_CC" \
|
||||
--compendium="$(unfmt gtk30)" \
|
||||
--compendium="$(unfmt gtk30-properties)" \
|
||||
"$PO_FILE" "$POT_FILE"
|
||||
update_po() {
|
||||
local LL_CC="$1"
|
||||
local PO_FILE="$POT_DIR/$LL_CC.po"
|
||||
|
||||
# /bin/sed --in-place --expression="s/Language: \\\\n/Language: $L_NAME\\\\n/" "$PO_FILE"
|
||||
test -r "$PO_FILE" || /usr/bin/msginit \
|
||||
--no-translator --locale="$LL_CC" \
|
||||
--input="$POT_FILE" \
|
||||
--output-file="$PO_FILE"
|
||||
|
||||
echo "Language file is $PO_FILE"
|
||||
/usr/bin/msgmerge \
|
||||
--update --no-fuzzy-matching \
|
||||
--no-escape --indent --add-location --sort-by-file \
|
||||
--lang="$LL_CC" \
|
||||
--compendium="$(unfmt gtk30)" \
|
||||
--compendium="$(unfmt gtk30-properties)" \
|
||||
"$PO_FILE" "$POT_FILE"
|
||||
|
||||
# /bin/sed --in-place --expression="s/Language: \\\\n/Language: $L_NAME\\\\n/" "$PO_FILE"
|
||||
echo "Updated $PO_FILE"
|
||||
}
|
||||
|
||||
if test "$1"; then
|
||||
update_po "$1"
|
||||
else
|
||||
for l in $(ls -1 "$POT_DIR"/??.po); do
|
||||
l="$(basename "$l")"
|
||||
update_po "${l%.po}"
|
||||
done
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue