diff --git a/README.md b/README.md index bbc7caa83..405658817 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ pgrep -af hamster ###### Ubuntu (tested in 19.04 and 18.04) ```bash -sudo apt install gettext intltool gconf2 gir1.2-gconf-2.0 python3-gi-cairo python3-distutils python3-dbus python3-xdg +sudo apt install gettext intltool python3-gi-cairo python3-distutils python3-dbus python3-xdg # and for documentation sudo apt install gnome-doc-utils yelp ``` @@ -70,7 +70,7 @@ sudo zypper install gnome-doc-utils xml2po yelp *RPM-based instructions below should be updated for python3 (issue [#369](https://github.com/projecthamster/hamster/issues/369)).* -`yum install gettext intltool gnome-python2-gconf dbus-python` +`yum install gettext intltool dbus-python` If the hamster help pages are not accessible ("unable to open `help:hamster-time-tracker`"), then a [Mallard](https://en.wikipedia.org/wiki/Mallard_(documentation))-capable help reader is required, diff --git a/data/hamster.desktop.in.in b/data/hamster.desktop.in.in index 24590c64f..a59274cd5 100644 --- a/data/hamster.desktop.in.in +++ b/data/hamster.desktop.in.in @@ -2,7 +2,7 @@ Version=1.0 Type=Application Terminal=false -_Name=Hamster Time Tracker +_Name=Hamster _Comment=Your personal time keeping tool Icon=hamster Exec=@BINDIR@/hamster diff --git a/data/hamster.metainfo.xml b/data/hamster.metainfo.xml index 5b6a177db..9667aa0f4 100644 --- a/data/hamster.metainfo.xml +++ b/data/hamster.metainfo.xml @@ -3,7 +3,7 @@ hamster CC0-1.0 GPL-3.0+ and CC-BY-SA-3.0 - Hamster Time Tracker + Hamster Your personal time keeping tool @@ -39,6 +39,7 @@ https://github.com/projecthamster/hamster/blob/master/data/screenshots/overview2.png + ​hamster https://github.com/projecthamster/hamster/wiki hamster diff --git a/data/hamster.schemas.in b/data/hamster.schemas.in deleted file mode 100644 index a89e33510..000000000 --- a/data/hamster.schemas.in +++ /dev/null @@ -1,143 +0,0 @@ - - - - /schemas/apps/hamster/enable_timeout - /apps/hamster/enable_timeout - hamster - bool - true - - Stop tracking on idle - - Stop tracking current activity when computer becomes idle - - - - - /schemas/apps/hamster/stop_on_shutdown - /apps/hamster/stop_on_shutdown - hamster - bool - false - - Stop tracking on shutdown - - Stop tracking current activity on shutdown - - - - - /schemas/apps/hamster/notify_interval - /apps/hamster/notify_interval - hamster - int - 27 - - Remind of current task every x minutes - - Remind of current task every specified amount of minutes. - Set to 0 or greater than 120 to disable reminder. - - - - - /schemas/apps/hamster/notify_on_idle - /apps/hamster/notify_on_idle - hamster - bool - false - - Also remind when no activity is set - - Also remind every notify_interval minutes if no activity - has been started. - - - - - /schemas/apps/hamster/day_start_minutes - /apps/hamster/day_start_minutes - hamster - int - 330 - - At what time does the day start (defaults to 5:30AM) - - Activities will be counted as to belong to yesterday if - the current time is less than the specified day start; and - today, if it is over the time. - Activities that span two days, will tip over to the side - where the largest part of the activity is. - - - - - /schemas/apps/hamster/workspace_tracking - /apps/hamster/workspace_tracking - hamster - list - string - [] - - Should workspace switch trigger activity switch - - List of enabled tracking methods. "name" will enable - switching activities by name defined in workspace_mapping. - "memory" will enable switching to the last activity when - returning to a previous workspace. - - - - - /schemas/apps/hamster/workspace_mapping - /apps/hamster/workspace_mapping - hamster - list - string - [] - - Switch activity on workspace change - - If switching by name is enabled, this list sets the activity - names that should be switched to, workspaces represented by - the index of item. - - - - - - - /schemas/desktop/gnome/keybindings/hamster/activate_hamster_window - /desktop/gnome/keybindings/hamster/activate_hamster_window - hamster - string - - - Show / hide Time Tracker Window - Keyboard shortcut for showing / hiding the Time Tracker window. - - - - /schemas/desktop/gnome/keybindings/hamster/action - /desktop/gnome/keybindings/hamster/action - hamster - string - hamster toggle - - Toggle hamster application window action - Command for toggling visibility of the hamster application window. - - - - /schemas/desktop/gnome/keybindings/hamster/name - /desktop/gnome/keybindings/hamster/name - hamster - string - Toggle hamster application window - - Toggle hamster application window - Toggle visibility of the hamster application window. - - - - diff --git a/data/org.gnome.hamster.gschema.xml b/data/org.gnome.hamster.gschema.xml new file mode 100644 index 000000000..dce4c1611 --- /dev/null +++ b/data/org.gnome.hamster.gschema.xml @@ -0,0 +1,22 @@ + + + + "" + The folder the last report was saved to + + The folder the last report was saved to + + + + + 330 + At what time does the day start (defaults to 5:30AM) + + The hamster day of an activity is the civil date of start time, + provided start time is after day-start. + On the contrary, if start time is earlier than day-start, + then the activity belongs to the previous hamster day. + + + + diff --git a/data/wscript_build b/data/wscript_build index 56a85bf8d..0acf4a77d 100644 --- a/data/wscript_build +++ b/data/wscript_build @@ -25,14 +25,6 @@ for filename in ["hamster.desktop"]: bld.add_group() -# process .in files with intl_tool -bld(features = 'intltool_in', - source = 'hamster.schemas.in', - target = 'hamster.schemas', - install_path = bld.env.schemas_destination, - podir = '../po', - flags = ['-s', '-u']) - bld(features = 'intltool_in', source = 'hamster.desktop.in', install_path = '${DATADIR}/applications', diff --git a/po/POTFILES.in b/po/POTFILES.in index 00a91f702..fadbe6a41 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -3,7 +3,7 @@ [type: gettext/glade]data/date_range.ui [type: gettext/glade]data/edit_activity.ui data/hamster.desktop.in.in -data/hamster.schemas.in +data/org.gnome.hamster.gschema.xml [type: gettext/glade]data/preferences.ui [type: gettext/python]src/hamster-cli src/hamster/about.py diff --git a/src/hamster/about.py b/src/hamster/about.py index 8069318f9..c6b3507ef 100644 --- a/src/hamster/about.py +++ b/src/hamster/about.py @@ -28,8 +28,7 @@ def __init__(self, parent = None): about = gtk.AboutDialog() self.window = about infos = { - "program-name" : _("Hamster Time Tracker"), - "name" : _("Time Tracker"), #this should be deprecated in gtk 2.10 + "program-name" : "Hamster", "version" : runtime.version, "comments" : _("Project Hamster — track your time"), "copyright" : _("Copyright © 2007–2010 Toms Bauģis and others"), diff --git a/src/hamster/lib/configuration.py b/src/hamster/lib/configuration.py index 1ce5df639..b26f3984d 100644 --- a/src/hamster/lib/configuration.py +++ b/src/hamster/lib/configuration.py @@ -18,7 +18,6 @@ # along with Project Hamster. If not, see . """ -gconf part of this code copied from Gimmie (c) Alex Gravely via Conduit (c) John Stowers, 2006 License: GPLv2 """ @@ -30,13 +29,11 @@ from xdg.BaseDirectory import xdg_data_home import datetime as dt +from gi.repository import Gio as gio +from gi.repository import GLib as glib from gi.repository import GObject as gobject from gi.repository import Gtk as gtk -import gi -gi.require_version('GConf', '2.0') -from gi.repository import GConf as gconf - class Controller(gobject.GObject): __gsignals__ = { @@ -191,149 +188,58 @@ def get_prefs_class(): dialogs = Dialogs() -class GConfStore(gobject.GObject, Singleton): +class GSettingsStore(gobject.GObject, Singleton): """ - Settings implementation which stores settings in GConf + Settings implementation which stores settings in GSettings Snatched from the conduit project (http://live.gnome.org/Conduit) """ - GCONF_DIR = "/apps/hamster/" - VALID_KEY_TYPES = (bool, str, int, list, tuple) - DEFAULTS = { - 'day_start_minutes' : 5 * 60 + 30, # At what time does the day start (5:30AM) - 'overview_window_box' : [], # X, Y, W, H - 'overview_window_maximized' : False, # Is overview window maximized - 'standalone_window_box' : [], # X, Y, W, H - 'standalone_window_maximized' : False, # Is overview window maximized - 'last_report_folder' : "~", # Path to directory where the last report was saved - } __gsignals__ = { - "conf-changed": (gobject.SignalFlags.RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)) + "changed": (gobject.SignalFlags.RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)) } + def __init__(self): gobject.GObject.__init__(self) - self._client = gconf.Client.get_default() - self._client.add_dir(self.GCONF_DIR[:-1], gconf.ClientPreloadType.PRELOAD_RECURSIVE) - self._notifications = [] - - def _fix_key(self, key): - """ - Appends the GCONF_PREFIX to the key if needed - - @param key: The key to check - @type key: C{string} - @returns: The fixed key - @rtype: C{string} - """ - if not key.startswith(self.GCONF_DIR): - return self.GCONF_DIR + key - else: - return key + self._settings = gio.Settings('org.gnome.Hamster') - def _key_changed(self, client, cnxn_id, entry, data=None): + def _key_changed(self, client, key, data=None): """ - Callback when a gconf key changes + Callback when a GSettings key changes """ - key = self._fix_key(entry.key)[len(self.GCONF_DIR):] - value = self._get_value(entry.value, self.DEFAULTS[key]) - - self.emit('conf-changed', key, value) - - - def _get_value(self, value, default): - """calls appropriate gconf function by the default value""" - vtype = type(default) - - if vtype is bool: - return value.get_bool() - elif vtype is str: - return value.get_string() - elif vtype is int: - return value.get_int() - elif vtype in (list, tuple): - l = [] - for i in value.get_list(): - l.append(i.get_string()) - return l - - return None + value = self._settings.get_value(key) + self.emit('changed', key, value) def get(self, key, default=None): """ Returns the value of the key or the default value if the key is - not yet in gconf + not yet in GSettings """ - - #function arguments override defaults - if default is None: - default = self.DEFAULTS.get(key, None) - vtype = type(default) - - #we now have a valid key and type - if default is None: - logger.warn("Unknown key: %s, must specify default value" % key) - return None - - if vtype not in self.VALID_KEY_TYPES: - logger.warn("Invalid key type: %s" % vtype) - return None - - #for gconf refer to the full key path - key = self._fix_key(key) - - if key not in self._notifications: - self._client.notify_add(key, self._key_changed, None) - self._notifications.append(key) - - value = self._client.get(key) + value = self._settings.get_value(key) if value is None: - self.set(key, default) - return default - - value = self._get_value(value, default) - if value is not None: - return value + logger.warn("Unknown GSettings key: %s" % key) - logger.warn("Unknown gconf key: %s" % key) - return None + return value.unpack() def set(self, key, value): """ - Sets the key value in gconf and connects adds a signal + Sets the key value in GSettings and connects adds a signal which is fired if the key changes """ logger.debug("Settings %s -> %s" % (key, value)) - if key in self.DEFAULTS: - vtype = type(self.DEFAULTS[key]) - else: - vtype = type(value) - - if vtype not in self.VALID_KEY_TYPES: - logger.warn("Invalid key type: %s" % vtype) - return False - - #for gconf refer to the full key path - key = self._fix_key(key) - - if vtype is bool: - self._client.set_bool(key, value) - elif vtype is str: - self._client.set_string(key, value) - elif vtype is int: - self._client.set_int(key, value) - elif vtype in (list, tuple): - #Save every value as a string - strvalues = [str(i) for i in value] - #self._client.set_list(key, gconf.VALUE_STRING, strvalues) - + default = self._settings.get_default_value(key) + assert default is not None + self._settings.set_value(key, glib.Variant(default.get_type().dup_string(), value)) return True + def bind(self, key, obj, prop): + self._settings.bind(key, obj, prop, gio.SettingsBindFlags.DEFAULT) + @property def day_start(self): """Start of the hamster day.""" - day_start_minutes = self.get("day_start_minutes") + day_start_minutes = self.get("day-start-minutes") hours, minutes = divmod(day_start_minutes, 60) return dt.time(hours, minutes) -conf = GConfStore() +conf = GSettingsStore() diff --git a/src/hamster/preferences.py b/src/hamster/preferences.py index 1f4a32225..7e0d1b7bd 100755 --- a/src/hamster/preferences.py +++ b/src/hamster/preferences.py @@ -507,9 +507,7 @@ def on_day_start_changed(self, widget): return day_start = day_start.hour * 60 + day_start.minute - - conf.set("day_start_minutes", day_start) - + conf.set("day-start-minutes", day_start) def on_close_button_clicked(self, button): self.close_window() diff --git a/src/hamster/widgets/reportchooserdialog.py b/src/hamster/widgets/reportchooserdialog.py index 5ff2822f3..0db0e981b 100644 --- a/src/hamster/widgets/reportchooserdialog.py +++ b/src/hamster/widgets/reportchooserdialog.py @@ -43,7 +43,7 @@ def __init__(self): gtk.ResponseType.OK)) # try to set path to last known folder or fall back to home - report_folder = os.path.expanduser(conf.get("last_report_folder")) + report_folder = os.path.expanduser(conf.get("last-report-folder")) if os.path.exists(report_folder): self.dialog.set_current_folder(report_folder) else: @@ -131,7 +131,7 @@ def on_save_button_clicked(self): categories = [] - conf.set("last_report_folder", os.path.dirname(path)) + conf.set("last-report-folder", os.path.dirname(path)) # format, path, start_date, end_date self.emit("report-chosen", format, path) diff --git a/wscript b/wscript index 034efb755..35700121b 100644 --- a/wscript +++ b/wscript @@ -10,7 +10,7 @@ from waflib import Logs, Utils def configure(conf): conf.load('gnu_dirs') # for DATADIR - + conf.load('glib2') # for GSettings support conf.load('python') conf.check_python_version(minver=(3,4,0)) @@ -23,16 +23,10 @@ def configure(conf): conf.env.GETTEXT_PACKAGE = "hamster" conf.env.PACKAGE = "hamster" - # gconf_dir is defined in options - conf.env.schemas_destination = '{}/schemas'.format(conf.options.gconf_dir) - conf.recurse("help") def options(opt): - opt.add_option('--gconf-dir', action='store', default='/etc/gconf', dest='gconf_dir', - help='gconf base directory [default: /etc/gconf]') - # the waf default value is /usr/local, which causes issues (e.g. #309) # opt.parser.set_defaults(prefix='/usr') did not update the help string, # hence need to replace the whole option @@ -81,27 +75,8 @@ def build(bld): bld.recurse("po data help") - - def manage_gconf_schemas(ctx, action): - """Install or uninstall hamster gconf schemas. - - Requires the stored hamster.schemas - (usually in /etc/gconf/schemas/) to be present. - - Hence install should be a post-fun, - and uninstall a pre-fun. - """ - - assert action in ("install", "uninstall") - if ctx.cmd == action: - schemas_file = "{}/hamster.schemas".format(ctx.env.schemas_destination) - cmd = 'GCONF_CONFIG_SOURCE=$(gconftool-2 --get-default-source) gconftool-2 --makefile-{}-rule {} 1> /dev/null'.format(action, schemas_file) - err = ctx.exec_command(cmd) - if err: - Logs.warn('The following command failed:\n{}'.format(cmd)) - else: - Logs.pprint('YELLOW', 'Successfully {}ed gconf schemas'.format(action)) - + bld(features='glib2', + settings_schema_files = ['data/org.gnome.hamster.gschema.xml']) def update_icon_cache(ctx): """Update the gtk icon cache.""" @@ -116,6 +91,4 @@ def build(bld): Logs.pprint('YELLOW', 'Successfully updated GTK icon cache') - bld.add_post_fun(lambda bld: manage_gconf_schemas(bld, "install")) bld.add_post_fun(update_icon_cache) - bld.add_pre_fun(lambda bld: manage_gconf_schemas(bld, "uninstall"))