replaced appinstance with GtkApplication
This commit is contained in:
parent
b01636e05d
commit
85efe92d30
|
@ -1,67 +0,0 @@
|
|||
#
|
||||
#
|
||||
#
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
import fcntl as _fcntl
|
||||
import os.path as _path
|
||||
import os as _os
|
||||
|
||||
from solaar import NAME
|
||||
_program = NAME.lower()
|
||||
del NAME
|
||||
|
||||
from logging import getLogger, DEBUG as _DEBUG
|
||||
_log = getLogger(__name__)
|
||||
del getLogger
|
||||
|
||||
|
||||
def check():
|
||||
"""Select a file lock location and try to acquire it.
|
||||
Suitable locations are $XDG_RUNTIME_DIR, /run/lock, /var/lock, and $TMPDIR.
|
||||
The first one found and writable is used.
|
||||
"""
|
||||
# ensure no more than a single instance runs at a time
|
||||
lock_fd = None
|
||||
for p in _os.environ.get('XDG_RUNTIME_DIR'), '/run/lock', '/var/lock', _os.environ.get('TMPDIR', '/tmp'):
|
||||
# pick the first temporary writable folder
|
||||
if p and _path.isdir(p) and _os.access(p, _os.W_OK):
|
||||
lock_path = _path.join(p, _program + '.single-instance.' + str(_os.getuid()))
|
||||
try:
|
||||
lock_fd = open(lock_path, 'wb')
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("single-instance lock file is %s", lock_path)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
if lock_fd:
|
||||
try:
|
||||
_fcntl.flock(lock_fd, _fcntl.LOCK_EX | _fcntl.LOCK_NB)
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("acquired single-instance lock %s", lock_fd)
|
||||
return lock_fd
|
||||
except IOError as e:
|
||||
if e.errno == 11:
|
||||
_log.warn("lock file is busy, %s already running: %s", _program, e)
|
||||
import sys
|
||||
sys.exit(_program + ": error: already running")
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
import sys
|
||||
print (_program + ": warning: no suitable location for the lockfile found; ignoring", file=sys.stderr)
|
||||
|
||||
|
||||
def close(lock_fd):
|
||||
"""Release a file lock."""
|
||||
if lock_fd:
|
||||
_fcntl.flock(lock_fd, _fcntl.LOCK_UN)
|
||||
lock_fd.close()
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("released single-instance lock %s", lock_fd)
|
|
@ -39,37 +39,31 @@ def _parse_arguments():
|
|||
return args
|
||||
|
||||
|
||||
def _run(args):
|
||||
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()
|
||||
ui.destroy()
|
||||
|
||||
listener.stop_all()
|
||||
|
||||
|
||||
def main():
|
||||
_require('pyudev', 'python-pyudev')
|
||||
_require('gi.repository', 'python-gi')
|
||||
_require('gi.repository.Gtk', 'gir1.2-gtk-3.0')
|
||||
args = _parse_arguments()
|
||||
_parse_arguments()
|
||||
|
||||
# handle ^C in console
|
||||
import signal
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
from . import appinstance
|
||||
appid = appinstance.check()
|
||||
try:
|
||||
# handle ^C in console
|
||||
import signal
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
_run(args)
|
||||
finally:
|
||||
appinstance.close(appid)
|
||||
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))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -5,13 +5,37 @@
|
|||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
|
||||
from logging import getLogger, DEBUG as _DEBUG
|
||||
from logging import getLogger, DEBUG as _DEBUG, INFO as _INFO
|
||||
_log = getLogger(__name__)
|
||||
del getLogger
|
||||
|
||||
from gi.repository import GLib, Gtk
|
||||
GLib.threads_init()
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def _init_application():
|
||||
app = Gtk.Application.new('io.github.pwr.solaar', 0)
|
||||
registered = app.register(None)
|
||||
if _log.isEnabledFor(_INFO):
|
||||
_log.info("application %s, registered %s", app.get_dbus_object_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()
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def _error_dialog(reason, object):
|
||||
_log.error("error: %s %s", reason, object)
|
||||
|
@ -67,7 +91,7 @@ def _process_async_queue():
|
|||
if function:
|
||||
function(*args, **kwargs)
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("stopped %s", t.name)
|
||||
_log.debug("stopped")
|
||||
|
||||
_queue_processor = Thread(name='AsyncUI', target=_process_async_queue)
|
||||
_queue_processor.daemon = True
|
||||
|
@ -80,7 +104,6 @@ def async(function, *args, **kwargs):
|
|||
task = (function, args, kwargs)
|
||||
_task_queue.put(task)
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
@ -89,21 +112,32 @@ from . import notify, tray, window
|
|||
|
||||
def init():
|
||||
notify.init()
|
||||
tray.init()
|
||||
tray.init(lambda _ignore: window.destroy())
|
||||
window.init()
|
||||
|
||||
def run_loop():
|
||||
Gtk.main()
|
||||
def _activate(app):
|
||||
assert app == application
|
||||
if app.get_windows():
|
||||
window.popup()
|
||||
else:
|
||||
app.add_window(window._window)
|
||||
|
||||
def destroy():
|
||||
# stop the async UI processor
|
||||
_queue_processor.alive = False
|
||||
async(None)
|
||||
def _shutdown(app):
|
||||
# stop the async UI processor
|
||||
_queue_processor.alive = False
|
||||
async(None)
|
||||
|
||||
tray.destroy()
|
||||
window.destroy()
|
||||
notify.uninit()
|
||||
tray.destroy()
|
||||
notify.uninit()
|
||||
|
||||
application.connect('activate', _activate)
|
||||
application.connect('shutdown', _shutdown)
|
||||
application.run(None)
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
from logitech.unifying_receiver.status import ALERT
|
||||
def _status_changed(device, alert, reason):
|
||||
|
|
|
@ -30,7 +30,7 @@ _RECEIVER_SEPARATOR = ('~', None, None, None)
|
|||
#
|
||||
#
|
||||
|
||||
def _create_menu():
|
||||
def _create_menu(quit_handler):
|
||||
menu = Gtk.Menu()
|
||||
|
||||
# per-device menu entries will be generated as-needed
|
||||
|
@ -42,7 +42,7 @@ def _create_menu():
|
|||
|
||||
from .action import about, make
|
||||
menu.append(about.create_menu_item())
|
||||
menu.append(make('application-exit', 'Quit', Gtk.main_quit).create_menu_item())
|
||||
menu.append(make('application-exit', 'Quit', quit_handler).create_menu_item())
|
||||
del about, make
|
||||
|
||||
menu.show_all()
|
||||
|
@ -424,10 +424,10 @@ _devices_info = []
|
|||
_menu = None
|
||||
_icon = None
|
||||
|
||||
def init():
|
||||
def init(_quit_handler):
|
||||
global _menu, _icon
|
||||
assert _menu is None
|
||||
_menu = _create_menu()
|
||||
_menu = _create_menu(_quit_handler)
|
||||
assert _icon is None
|
||||
_icon = _create(_menu)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ Name=Solaar
|
|||
Comment=Logitech Unifying Receiver peripherals manager
|
||||
Exec=solaar
|
||||
Icon=solaar
|
||||
StartupNotify=false
|
||||
StartupNotify=true
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Keywords=logitech;unifying;receiver;mouse;keyboard;
|
||||
|
|
Loading…
Reference in New Issue