Merge branch 'master' into finnish

Conflicts:
	po/solaar.pot - run tools/po-compile.sh
This commit is contained in:
Tomi Leppänen 2013-08-11 16:48:12 +03:00
commit 372e4e0949
34 changed files with 2117 additions and 866 deletions

View File

@ -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.

View File

@ -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

View File

@ -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()

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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')

View File

@ -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

View File

@ -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__

70
lib/solaar/async.py Normal file
View File

@ -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")

View File

@ -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()

154
lib/solaar/cli/__init__.py Normal file
View File

@ -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))

120
lib/solaar/cli/config.py Normal file
View File

@ -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)

91
lib/solaar/cli/pair.py Normal file
View File

@ -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)

146
lib/solaar/cli/show.py Normal file
View File

@ -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)

36
lib/solaar/cli/unpair.py Normal file
View File

@ -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))

View File

@ -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))

View File

@ -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):

View File

@ -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/')

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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-*).

453
po/fr.po Normal file
View File

@ -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"

View File

@ -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"

View File

@ -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ă"

View File

@ -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 ""

451
po/sv.po Normal file
View File

@ -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"

View File

@ -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

View File

@ -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