diff --git a/data/org.gnome.hamster.gschema.xml b/data/org.gnome.hamster.gschema.xml
index dce4c1611..d952b0f47 100644
--- a/data/org.gnome.hamster.gschema.xml
+++ b/data/org.gnome.hamster.gschema.xml
@@ -7,6 +7,14 @@
The folder the last report was saved to
+
+
+ false
+ Stop tracking on shutdown
+
+ Stop tracking current activity on shutdown
+
+ 330
diff --git a/data/preferences.ui b/data/preferences.ui
index 37c81ecb3..fd9b67351 100644
--- a/data/preferences.ui
+++ b/data/preferences.ui
@@ -40,6 +40,22 @@
startvertical8
+
+
+
+ False
+ True
+ 0
+
+
diff --git a/src/hamster-service.py b/src/hamster-service.py
index 4b1e43a71..fb3cae146 100644
--- a/src/hamster-service.py
+++ b/src/hamster-service.py
@@ -13,6 +13,7 @@
i18n.setup_i18n() # noqa: E402
from hamster.storage import db
+from hamster.session import DbusSessionListener
from hamster.lib import datetime as dt
from hamster.lib import default_logger
from hamster.lib.dbus import (
@@ -26,6 +27,7 @@
to_dbus_fact_json
)
from hamster.lib.fact import Fact, FactError
+from hamster.lib.configuration import conf
logger = default_logger(__file__)
@@ -38,7 +40,7 @@
quit()
-class Storage(db.Storage, dbus.service.Object):
+class Storage(db.Storage, dbus.service.Object, DbusSessionListener):
__dbus_object_path__ = "/org/gnome/Hamster"
def __init__(self, loop):
@@ -50,6 +52,7 @@ def __init__(self, loop):
db.Storage.__init__(self, unsorted_localized="")
self.mainloop = loop
+ DbusSessionListener.__init__(self)
self.__file = gio.File.new_for_path(__file__)
self.__monitor = self.__file.monitor_file(gio.FileMonitorFlags.WATCH_MOUNTS | \
@@ -79,6 +82,12 @@ def run_fixtures(self):
self.add_activity(activity, cat_id)
+ # stop current task on log out if requested
+ def end_session(self):
+ """Stop tracking on logout."""
+ if conf.get("stop-on-shutdown"):
+ self.stop_tracking(None)
+
# stop service when we have been updated (will be brought back in next call)
# anyway. should make updating simpler
def _on_us_change(self, monitor, gio_file, event_uri, event):
diff --git a/src/hamster/preferences.py b/src/hamster/preferences.py
index c41b1d35c..1a44fa12d 100644
--- a/src/hamster/preferences.py
+++ b/src/hamster/preferences.py
@@ -169,6 +169,8 @@ def show(self):
self.window.show_all()
def load_config(self, *args):
+ conf.bind("stop-on-shutdown", self.get_widget("shutdown_track"), "active")
+
self.day_start.time = conf.day_start
self.tags = [tag["name"] for tag in runtime.storage.get_tags(only_autocomplete=True)]
diff --git a/src/hamster/session.py b/src/hamster/session.py
new file mode 100644
index 000000000..75dcaed36
--- /dev/null
+++ b/src/hamster/session.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2020 Sébastien Granjoux
+
+# This file is part of Project Hamster.
+
+# Project Hamster 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 3 of the License, or
+# (at your option) any later version.
+
+# Project Hamster 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 Project Hamster. If not, see .
+
+import dbus
+import logging
+logger = logging.getLogger(__name__)
+
+class DbusSessionListener(object):
+ """Listen for GNOME manager end session event."""
+
+
+ def end_session(self):
+ """Override this method to do something at the end of a session.
+ It must not attempt to interact with the user and will be given
+ a maximum of ten seconds to perform the actions."""
+ pass
+
+
+ def __init__(self):
+ """Connect to the GNOME manager session signals"""
+
+ # Get SessionManager interface
+ session_bus = dbus.SessionBus()
+ try:
+ session_manager = session_bus.get_object("org.gnome.SessionManager",
+ "/org/gnome/SessionManager")
+ self.__session_manager_iface = dbus.Interface(session_manager,
+ dbus_interface="org.gnome.SessionManager")
+ self.__client_id = self.__session_manager_iface.RegisterClient("", "")
+
+ # Get SessionManager.ClientPrivate interface
+ session_client = session_bus.get_object("org.gnome.SessionManager",
+ self.__client_id)
+ self.__session_client_private_iface = dbus.Interface(session_client,
+ dbus_interface="org.gnome.SessionManager.ClientPrivate")
+
+ # Connect to the needed signals
+ session_bus.add_signal_receiver(self.__query_end_session_handler,
+ signal_name = "QueryEndSession",
+ dbus_interface = "org.gnome.SessionManager.ClientPrivate",
+ bus_name = "org.gnome.SessionManager")
+
+ session_bus.add_signal_receiver(self.__end_session_handler,
+ signal_name = "EndSession",
+ dbus_interface = "org.gnome.SessionManager.ClientPrivate",
+ bus_name = "org.gnome.SessionManager")
+
+ session_bus.add_signal_receiver(self.__stop_handler,
+ signal_name = "Stop",
+ dbus_interface = "org.gnome.SessionManager.ClientPrivate",
+ bus_name = "org.gnome.SessionManager")
+ except dbus.exceptions.DBusException:
+ logger.info("Unable to connect to GNOME session manager, stop tracking on logout won't work")
+
+ def __query_end_session_handler(self, flags):
+ """Inform that the session is about to end. It must reply with
+ EndSessionResponse within one second telling if it is ok to proceed
+ or not and why. If flags is true, the session will end anyway."""
+ self.__session_client_private_iface.EndSessionResponse(True, "")
+
+ def __end_session_handler(self, flags):
+ """Inform that the session is about to end. It must reply with
+ EndSessionResponse within ten seconds."""
+ self.end_session()
+ self.__session_client_private_iface.EndSessionResponse(True, "")
+
+ def __stop_handler(self):
+ """Remove from the session."""
+ self.__session_manager_iface.UnregisterClient(self.__client_id)