def run(cli_args=None, hidraw_path=None): if cli_args: action = cli_args[0] args = _cli_parser.parse_args(cli_args) else: args = _cli_parser.parse_args() # Python 3 has an undocumented 'feature' that breaks parsing empty args # http://bugs.python.org/issue16308 if not 'cmd' in args: _cli_parser.print_usage(_sys.stderr) _sys.stderr.write('%s: error: too few arguments\n' % NAME.lower()) _sys.exit(2) action = args.action assert action in actions try: c = list(_receivers(hidraw_path)) 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))
def run(cli_args=None, hidraw_path=None): if cli_args: action = cli_args[0] args = _cli_parser.parse_args(cli_args) else: args = _cli_parser.parse_args() # Python 3 has an undocumented 'feature' that breaks parsing empty args # http://bugs.python.org/issue16308 if not 'cmd' in args: _cli_parser.print_usage(_sys.stderr) _sys.stderr.write('%s: error: too few arguments\n' % NAME.lower()) _sys.exit(2) action = args.action assert action in actions try: c = list(_receivers(hidraw_path)) 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 AssertionError as e: from traceback import extract_tb tb_last = extract_tb(_sys.exc_info()[2])[-1] _sys.exit('%s: assertion failed: %s line %d' % (NAME.lower(), tb_last[0], tb_last[1])) except Exception as e: _sys.exit('%s: error: %s' % (NAME.lower(), e))
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 number, ' 'a substring of a device\'s name, or "all" (the default)' ) sp.set_defaults(action='show') sp = subparsers.add_parser('probe', help='probe a receiver (debugging use only)') sp.add_argument( 'receiver', nargs='?', help='select receiver by name substring or serial number when more than one is present' ) sp.set_defaults(action='probe') 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 serial number, ' 'or a substring of a device\'s name' ) sp.add_argument('setting', nargs='?', help='device-specific setting; leave empty to list available settings') sp.add_argument('value_key', nargs='?', help='new value for the setting or key for keyed settings') sp.add_argument('extra_subkey', nargs='?', help='value for keyed or subkey for subkeyed settings') sp.add_argument('extra2', nargs='?', help='value for subkeyed settings') 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 receiver by name substring or serial number 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 number, ' 'or a substring of a device\'s name.' ) sp.set_defaults(action='unpair') return parser, subparsers.choices
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) _details = _create_details_panel() _info = _create_info_panel() _empty = _create_empty_panel() _window = _create()
def init(show_window, hide_on_close): 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) _details = _create_details_panel() _info = _create_info_panel() _empty = _create_empty_panel() _window = _create(_hide if hide_on_close else destroy) if show_window: _window.present()
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) 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() except Exception as e: import sys sys.exit('%s: error: %s' % (NAME.lower(), e))
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)" ) arg_parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__) args = arg_parser.parse_args() import logging if args.debug > 0: log_level = logging.WARNING - 10 * args.debug log_format = '%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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) 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', 'python3-pyudev') # handle ^C in console import signal signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGINT, _handlesigint) args = _parse_arguments() if not args: return if args.action: # if any argument, run comandline and exit return _cli.run(args.action, args.hidraw_path) gi = _require('gi', 'python3-gi or python3-gobject') _require('gi.repository.Gtk', 'gir1.2-gtk-3.0', gi, 'Gtk', '3.0') try: import solaar.ui as ui import solaar.listener as listener listener.setup_scanner(ui.status_changed, ui.error_dialog) import solaar.upower as _upower if args.restart_on_wake_up: _upower.watch(listener.start_all, listener.stop_all) else: _upower.watch(lambda: listener.ping_all(True)) # main UI event loop ui.run_loop(listener.start_all, listener.stop_all, args.window != 'only', args.window != 'hide') except Exception: import sys from traceback import format_exc sys.exit('%s: error: %s' % (NAME.lower(), format_exc()))
def _create(): about = Gtk.AboutDialog() about.set_program_name(NAME) about.set_version(__version__) about.set_comments( _('Manages Logitech receivers,\nkeyboards, mice, and tablets.')) about.set_logo_icon_name(NAME.lower()) about.set_copyright( '© 2012-2021 Daniel Pavel and contributors to the Solaar project') about.set_license_type(Gtk.License.GPL_2_0) about.set_authors(('Daniel Pavel http://github.com/pwr', )) try: about.add_credit_section(_('Additional Programming'), ('Filipe Laíns', 'Peter F. Patel-Schneider')) about.add_credit_section(_('GUI design'), ('Julien Gascard', 'Daniel Pavel')) about.add_credit_section(_('Testing'), ( 'Douglas Wagner', 'Julien Gascard', 'Peter Wu http://www.lekensteyn.nl/logitech-unifying.html', )) about.add_credit_section(_('Logitech documentation'), ( 'Julien Danjou http://julien.danjou.info/blog/2012/logitech-unifying-upower', 'Nestor Lopez Casado http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28', )) except TypeError: # gtk3 < ~3.6.4 has incorrect gi bindings import logging logging.exception('failed to fully create the about dialog') except Exception: # the Gtk3 version may be too old, and the function does not exist import logging logging.exception('failed to fully create the about dialog') about.set_translator_credits('\n'.join(( 'gogo (croatian)', 'Papoteur, David Geiger, Damien Lallement (français)', 'Michele Olivo (italiano)', 'Adrian Piotrowicz (polski)', 'Drovetto, JrBenito (Portuguese-BR)', 'Daniel Pavel (română)', 'Daniel Zippert, Emelie Snecker (svensk)', 'Dimitriy Ryazantcev (Russian)', ))) about.set_website('https://pwr-solaar.github.io/Solaar') about.set_website_label(NAME) about.connect('response', lambda x, y: x.hide()) def _hide(dialog, event): dialog.hide() return True about.connect('delete-event', _hide) return about
def show(dev, reason=None, icon=None): """Show a notification with title and text.""" if available and Notify.is_initted(): summary = dev.name # if a notification with same name is already visible, reuse it to avoid spamming n = _notifications.get(summary) if n is None: n = _notifications[summary] = Notify.Notification() if reason: message = reason elif dev.status is None: message = _('unpaired') elif bool(dev.status): message = dev.status.to_string() 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 icon_file = _icons.device_icon_file( dev.name, dev.kind) if icon is None else _icons.icon_file(icon) n.update(summary, message, icon_file) urgency = Notify.Urgency.LOW if dev.status else Notify.Urgency.NORMAL n.set_urgency(urgency) n.set_hint('desktop-entry', GLib.Variant('s', NAME.lower())) try: # if _log.isEnabledFor(_DEBUG): # _log.debug("showing %s", n) n.show() except Exception: _log.exception('showing %s', n)
def main(): _require('pyudev', 'python-pyudev') # handle ^C in console import signal signal.signal(signal.SIGINT, signal.SIG_DFL) args = _parse_arguments() if not args: return if args.action: # if any argument, run comandline and exit return _cli.run(args.action, args.hidraw_path) gi = _require('gi', 'python-gi') gi.require_version('Gtk', '3.0') _require('gi.repository.Gtk', 'gir1.2-gtk-3.0') try: import solaar.ui as ui import solaar.listener as listener listener.setup_scanner(ui.status_changed, ui.error_dialog) import solaar.upower as _upower if args.restart_on_wake_up: _upower.watch(listener.start_all, listener.stop_all) else: _upower.watch(listener.ping_all) # main UI event loop ui.run_loop(listener.start_all, listener.stop_all) except Exception as e: import sys sys.exit('%s: error: %s' % (NAME.lower(), e))
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)') 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') arg_parser.add_argument('--restart-on-wake-up', action='store_true', help='restart Solaar on sleep wake-up (experimental)') 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: _cli.print_help() return import logging if args.debug > 0: log_level = logging.WARNING - 10 * args.debug log_format='%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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) if not 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 _parse_arguments(): import argparse arg_parser = argparse.ArgumentParser( prog=NAME.lower(), epilog='For more information see https://pwr-solaar.github.io/Solaar' ) 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( '-D', '--hidraw', action='store', dest='hidraw_path', metavar='PATH', help='unifying receiver to use; the first detected receiver if unspecified. Example: /dev/hidraw2' ) arg_parser.add_argument('--restart-on-wake-up', action='store_true', help='restart Solaar on sleep wake-up (experimental)') arg_parser.add_argument( '-w', '--window', choices=('show', 'hide', 'only'), help='start with window showing / hidden / only (no tray icon)' ) arg_parser.add_argument( '-b', '--battery-icons', choices=('regular', 'symbolic', 'solaar'), help='prefer regular battery / symbolic battery / solaar icons' ) 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: _cli.print_help() return if args.window is None: args.window = 'show' # default behaviour is to show main window global battery_icons_style battery_icons_style = args.battery_icons if args.battery_icons is not None else 'regular' import logging if args.debug > 0: log_level = logging.WARNING - 10 * args.debug log_format = '%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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) if not 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 _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)' ) 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' ) arg_parser.add_argument( '--restart-on-wake-up', action='store_true', help='restart Solaar on sleep wake-up (experimental)') 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: _cli.print_help() return import logging if args.debug > 0: log_level = logging.WARNING - 10 * args.debug log_format = '%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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) if not 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 _create(): about = Gtk.AboutDialog() about.set_program_name(NAME) about.set_version(__version__) about.set_comments( _("Shows status of devices connected\nthrough wireless Logitech receivers." )) about.set_logo_icon_name(NAME.lower()) about.set_copyright('© 2012-2013 Daniel Pavel') about.set_license_type(Gtk.License.GPL_2_0) about.set_authors(('Daniel Pavel http://github.com/pwr', )) try: about.add_credit_section(_("GUI design"), ('Julien Gascard', 'Daniel Pavel')) about.add_credit_section(_("Testing"), ( 'Douglas Wagner', 'Julien Gascard', 'Peter Wu http://www.lekensteyn.nl/logitech-unifying.html', )) about.add_credit_section(_("Logitech documentation"), ( 'Julien Danjou http://julien.danjou.info/blog/2012/logitech-unifying-upower', 'Nestor Lopez Casado http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28', )) except TypeError: # gtk3 < ~3.6.4 has incorrect gi bindings import logging logging.exception("failed to fully create the about dialog") except: # the Gtk3 version may be too old, and the function does not exist import logging logging.exception("failed to fully create the about dialog") about.set_translator_credits('\n'.join(( 'gogo (croatian)', 'Papoteur, David Geiger, Damien Lallement (français)', 'Michele Olivo (italiano)', 'Adrian Piotrowicz (polski)', 'Drovetto, JrBenito (Portuguese-BR)', 'Daniel Pavel (română)', 'Daniel Zippert, Emelie Snecker (svensk)', ))) about.set_website('http://pwr.github.io/Solaar/') about.set_website_label(NAME) about.connect('response', lambda x, y: x.hide()) def _hide(dialog, event): dialog.hide() return True about.connect('delete-event', _hide) return about
def _handlesigint(signal, stack): import signal import sys import faulthandler signal.signal(signal.SIGINT, signal.SIG_DFL) if _log.isEnabledFor(_INFO): faulthandler.dump_traceback() sys.exit('%s: exit due to keyboard interrupt' % (NAME.lower()))
def _create(): about = Gtk.AboutDialog() about.set_program_name(NAME) about.set_version(__version__) about.set_comments(_("Shows status of devices connected\nthrough wireless Logitech receivers.")) about.set_logo_icon_name(NAME.lower()) about.set_copyright('© 2012-2013 Daniel Pavel') about.set_license_type(Gtk.License.GPL_2_0) about.set_authors(('Daniel Pavel http://github.com/pwr',)) try: about.add_credit_section(_("GUI design"), ('Julien Gascard', 'Daniel Pavel')) about.add_credit_section(_("Testing"), ( 'Douglas Wagner', 'Julien Gascard', 'Peter Wu http://www.lekensteyn.nl/logitech-unifying.html', )) about.add_credit_section(_("Logitech documentation"), ( 'Julien Danjou http://julien.danjou.info/blog/2012/logitech-unifying-upower', 'Nestor Lopez Casado http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28', )) except TypeError: # gtk3 < ~3.6.4 has incorrect gi bindings import logging logging.exception("failed to fully create the about dialog") except: # the Gtk3 version may be too old, and the function does not exist import logging logging.exception("failed to fully create the about dialog") about.set_translator_credits('\n'.join(( 'gogo (croatian)', 'Papoteur, David Geiger, Damien Lallement (français)', 'Michele Olivo (italiano)', 'Adrian Piotrowicz (polski)', 'Drovetto, JrBenito (Portuguese-BR)', 'Daniel Pavel (română)', 'Daniel Zippert, Emelie Snecker (svensk)', 'Dimitriy Ryazantcev (Russian)', ))) about.set_website('http://pwr.github.io/Solaar/') about.set_website_label(NAME) about.connect('response', lambda x, y: x.hide()) def _hide(dialog, event): dialog.hide() return True about.connect('delete-event', _hide) return about
def alert(reason, icon=None): assert reason if available and Notify.is_initted(): n = _notifications.get(NAME) if n is None: n = _notifications[NAME] = Notify.Notification() # we need to use the filename here because the notifications daemon # is an external application that does not know about our icon sets icon_file = _icons.icon_file( NAME.lower()) if icon is None else _icons.icon_file(icon) n.update(NAME, reason, icon_file) n.set_urgency(Notify.Urgency.NORMAL) n.set_hint('desktop-entry', GLib.Variant('s', NAME.lower())) try: # if _log.isEnabledFor(_DEBUG): # _log.debug("showing %s", n) n.show() except Exception: _log.exception('showing %s', n)
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.add_argument('--battery', action='store_true', default=False, help='show battery level only') 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
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)", ) 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", ) arg_parser.add_argument( "--restart-on-wake-up", action="store_true", help="restart Solaar on sleep wake-up (experimental)" ) 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: _cli.print_help() return import logging if args.debug > 0: log_level = logging.WARNING - 10 * args.debug log_format = "%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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) if not 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', 'python3-pyudev') # handle ^C in console import signal signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGINT, _handlesigint) args = _parse_arguments() if not args: return if args.action: # if any argument, run comandline and exit return _cli.run(args.action, args.hidraw_path) gi = _require('gi', 'python3-gi or python3-gobject') _require('gi.repository.Gtk', 'gir1.2-gtk-3.0', gi, 'Gtk', '3.0') udev_file = '42-logitech-unify-permissions.rules' if not os.path.isfile('/etc/udev/rules.d/' + udev_file) and not os.path.isfile( '/lib/udev/rules.d/' + udev_file): print(_i18n._('ERROR: '), end='') print(_i18n._('Solaar depends on a udev file that is not present'), end='.\n') print( _i18n._( 'For more information see the Solaar installation directions\n' 'at https://pwr-solaar.github.io/Solaar/installation')) try: import solaar.ui as ui import solaar.listener as listener listener.setup_scanner(ui.status_changed, ui.error_dialog) import solaar.upower as _upower if args.restart_on_wake_up: _upower.watch(listener.start_all, listener.stop_all) else: _upower.watch(lambda: listener.ping_all(True)) # main UI event loop ui.run_loop(listener.start_all, listener.stop_all, args.window != 'only', args.window != 'hide') except Exception: import sys from traceback import format_exc sys.exit('%s: error: %s' % (NAME.lower(), format_exc()))
def main(): _require('pyudev', 'python3-pyudev') # handle ^C in console import signal signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGINT, _handlesigint) args = _parse_arguments() if not args: return if args.action: # if any argument, run comandline and exit return _cli.run(args.action, args.hidraw_path) gi = _require('gi', 'python3-gi (in Ubuntu) or python3-gobject (in Fedora)') _require('gi.repository.Gtk', 'gir1.2-gtk-3.0', gi, 'Gtk', '3.0') udev_file = '42-logitech-unify-permissions.rules' if _log.isEnabledFor(_WARNING) \ and not os.path.isfile('/etc/udev/rules.d/' + udev_file) \ and not os.path.isfile('/usr/lib/udev/rules.d/' + udev_file) \ and not os.path.isfile('/usr/local/lib/udev/rules.d/' + udev_file): _log.warning('Solaar udev file not found in expected location') _log.warning( 'See https://pwr-solaar.github.io/Solaar/installation for more information' ) try: import solaar.ui as ui import solaar.listener as listener listener.setup_scanner(ui.status_changed, ui.error_dialog) import solaar.upower as _upower if args.restart_on_wake_up: _upower.watch(listener.start_all, listener.stop_all) else: _upower.watch(lambda: listener.ping_all(True)) # main UI event loop ui.run_loop(listener.start_all, listener.stop_all, args.window != 'only', args.window != 'hide') except Exception: import sys from traceback import format_exc sys.exit('%s: error: %s' % (NAME.lower(), format_exc()))
def run(cli_args=None): 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))
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)") arg_parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__) args = arg_parser.parse_args() import logging if args.debug > 0: log_level = logging.WARNING - 10 * args.debug log_format='%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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) if logging.root.isEnabledFor(logging.INFO): logging.info("language %s (%s), translations path %s", _i18n.language, _i18n.encoding, _i18n.path) return args
def alert(reason, icon=None): assert reason if available and Notify.is_initted(): n = _notifications.get(NAME) if n is None: n = _notifications[NAME] = Notify.Notification() # we need to use the filename here because the notifications daemon # is an external application that does not know about our icon sets icon_file = _icons.icon_file(NAME.lower()) if icon is None \ else _icons.icon_file(icon) n.update(NAME, reason, icon_file) n.set_urgency(Notify.Urgency.NORMAL) try: # if _log.isEnabledFor(_DEBUG): # _log.debug("showing %s", n) n.show() except Exception: _log.exception("showing %s", n)
from os.path import dirname as _dirname yield 'share/solaar/icons', _glob('share/solaar/icons/solaar*.svg') yield 'share/solaar/icons', _glob('share/solaar/icons/light_*.png') yield 'share/icons/hicolor/scalable/apps', ['share/solaar/icons/solaar.svg'] for mo in _glob('share/locale/*/LC_MESSAGES/solaar.mo'): yield _dirname(mo), [mo] yield 'share/applications', ['share/applications/solaar.desktop'] yield autostart_path, ['share/applications/solaar.desktop'] del _dirname setup(name=NAME.lower(), version=__version__, description='Linux devices manager for the Logitech Unifying Receiver.', long_description=''' Solaar is a Linux device manager for Logitech's Unifying Receiver peripherals. It is able to pair/unpair devices to the receiver, and for some devices read battery status. '''.strip(), author='Daniel Pavel', author_email='*****@*****.**', license='GPLv2', url='http://pwr.github.io/Solaar/', classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: X11 Applications :: GTK', 'Environment :: Console',
del _sys from glob import glob as _glob for location in prefix_share, src_share: mo_files = _glob(_path.join(location, 'locale', '*', 'LC_MESSAGES', lc_domain + '.mo')) if mo_files: return _path.join(location, 'locale') # del _path locale.setlocale(locale.LC_ALL, '') language, encoding = locale.getlocale() del locale _LOCALE_DOMAIN = _NAME.lower() path = _find_locale_path(_LOCALE_DOMAIN) _gettext.bindtextdomain(_LOCALE_DOMAIN, path) _gettext.textdomain(_LOCALE_DOMAIN) _gettext.install(_LOCALE_DOMAIN) try: unicode # noqa: F821 _ = lambda x: _gettext.gettext(x).decode('UTF-8') ngettext = lambda *x: _gettext.ngettext(*x).decode('UTF-8') except Exception: _ = _gettext.gettext ngettext = _gettext.ngettext
from glob import glob as _glob for location in prefix_share, src_share: mo_files = _glob(_path.join(location, 'locale', '*', 'LC_MESSAGES', lc_domain + '.mo')) if mo_files: return _path.join(location, 'locale') # del _path import locale locale.setlocale(locale.LC_ALL, '') language, encoding = locale.getlocale() del locale _LOCALE_DOMAIN = _NAME.lower() path = _find_locale_path(_LOCALE_DOMAIN) import gettext as _gettext _gettext.bindtextdomain(_LOCALE_DOMAIN, path) _gettext.textdomain(_LOCALE_DOMAIN) _gettext.install(_LOCALE_DOMAIN) try: unicode _ = lambda x: _gettext.gettext(x).decode('UTF-8') except: _ = _gettext.gettext
yield 'share/solaar/icons', _glob('share/solaar/icons/light_*.png') yield 'share/icons/hicolor/scalable/apps', [ 'share/solaar/icons/solaar.svg' ] for mo in _glob('share/locale/*/LC_MESSAGES/solaar.mo'): yield _dirname(mo), [mo] yield 'share/applications', ['share/applications/solaar.desktop'] yield autostart_path, ['share/applications/solaar.desktop'] del _dirname setup( name=NAME.lower(), version=__version__, description='Linux devices manager for the Logitech Unifying Receiver.', long_description=''' Solaar is a Linux device manager for Logitech's Unifying Receiver peripherals. It is able to pair/unpair devices to the receiver, and for some devices read battery status. '''.strip(), author='Daniel Pavel', author_email='*****@*****.**', license='GPLv2', url='http://pwr.github.io/Solaar/', classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: X11 Applications :: GTK', 'Environment :: Console',
"because typed text can be sniffed inconspicuously by 3rd parties within range.") _UNIFYING_RECEIVER_TEXT = ( _("No device paired") + '.\n\n<small>' + _("Up to %d devices can be paired to this receiver") + '.</small>', '%d ' + _("paired devices") + '\n\n<small>' + _("Up to %d devices can be paired to this receiver") + '.</small>', ) _NANO_RECEIVER_TEXT = ( _("No device paired") + '.\n\n<small> </small>', ' \n\n<small>' + _("Only one device can be paired to this receiver") + '.</small>', ) # # 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() else: b = Gtk.Button(label) if label else Gtk.Button() if icon_name: image = Gtk.Image.new_from_icon_name(icon_name, icon_size) b.set_image(image) if tooltip: b.set_tooltip_text(tooltip)