replaced appinstance with GtkApplication

This commit is contained in:
Daniel Pavel 2013-07-09 17:52:07 +02:00
parent b01636e05d
commit 85efe92d30
5 changed files with 70 additions and 109 deletions

View File

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

View File

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

View File

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

View File

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

View File

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