Skip to content

Commit

Permalink
Fix notifications
Browse files Browse the repository at this point in the history
The code for notifications was removed somewhere in the history.
With this commit, notifications are expected to work as usual!

Signed-off-by: Sharaf Zaman <sharafzaz121@gmail.com>
  • Loading branch information
sh-zam committed Feb 18, 2020
1 parent d9b2a55 commit 88eb65f
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 1 deletion.
15 changes: 15 additions & 0 deletions data/org.gnome.hamster.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,20 @@
then the activity belongs to the previous hamster day.
</description>
</key>

<key type="u" name="notify-interval-minutes">
<default>15</default>
<summary>After how many minutes to notify the user</summary>
</key>

<key type="b" name="notifications-enabled">
<default>false</default>
<summary>Enable notifications</summary>
</key>

<key type="b" name="notify-on-idle-enabled">
<default>false</default>
<summary>Send Notifications when no activity is set</summary>
</key>
</schema>
</schemalist>
88 changes: 88 additions & 0 deletions data/preferences.ui
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
<!-- Generated with glade 3.20.4 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkAdjustment" id="adjustment1">
<property name="upper">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkTextBuffer" id="autocomplete_tags"/>
<object class="GtkWindow" id="window">
<property name="can_focus">False</property>
Expand Down Expand Up @@ -40,6 +45,89 @@
<property name="valign">start</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkBox" id="box1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="notifs-enabled-toggle">
<property name="label" translatable="yes">Send notifications</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">-1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="notification-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">20</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Remind of current activity every: </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScale" id="notify-interval-scale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment1</property>
<property name="fill_level">120</property>
<property name="round_digits">0</property>
<property name="digits">0</property>
<property name="value_pos">right</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="notify-on-idle">
<property name="label" translatable="yes">Also remind when no activity is set</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="_notify_on_idle_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">2</property>
<property name="position">4</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="day-start box">
<property name="visible">True</property>
Expand Down
2 changes: 1 addition & 1 deletion src/hamster-cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
from hamster.lib import default_logger, stuff
from hamster.lib import datetime as dt
from hamster.lib.fact import Fact

from hamster.lib.notifsmanager import notifs_mgr

logger = default_logger(__file__)

Expand Down
14 changes: 14 additions & 0 deletions src/hamster/lib/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,5 +181,19 @@ def day_start(self):
hours, minutes = divmod(day_start_minutes, 60)
return dt.time(hours, minutes)

@property
def notify_interval(self):
"""Notifications every X minutes"""
return self.get("notify-interval-minutes")

@property
def notifications_enabled(self):
"""Enable/Disable notifications"""
return self.get("notifications-enabled")

@property
def notify_on_idle(self) -> bool:
"""Enable/Disable notifications when no activity is set"""
return self.get("notify-on-idle-enabled")

conf = GSettingsStore()
118 changes: 118 additions & 0 deletions src/hamster/lib/notifsmanager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# - coding: utf-8 -

# Copyright (C) 2020 Sharaf Zaman <sharafzaz121@gmail.com>

# 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 <http://www.gnu.org/licenses/>.

import logging
logger = logging.getLogger(__name__) # noqa: E402
import datetime
import dbus
import hamster.client

from gi.repository import Gtk
from gi.repository import GObject as gobject
from hamster.lib.configuration import conf


class Notification(object):
def __init__(self):
self.bus = dbus.SessionBus()
self.appname = "Hamster Time Tracker"
self.replace_id = 0
# FIXME: icon location?
self.icon = "/usr/share/hamster-time-tracker/art/hamster-time-tracker.png"
self.summary = "Hamster Time Tracker"
self.hints = {}
self.actions = []
self.data = {}
self.timeout = -1

def show(self, message):
"""
Show notitification
returns: True if successful
"""
try:
self.server = dbus.Interface(self.bus.get_object("org.freedesktop.Notifications",
"/org/freedesktop/Notifications"),
dbus_interface="org.freedesktop.Notifications")
except dbus.exceptions.DBusException as e:
# TODO: Log?
logger.error(e)
logger.warning("Notifications will be disabled")
return False

try:
self.server.Notify(self.appname,
self.replace_id,
self.icon,
self.summary,
message,
self.actions,
self.hints,
self.timeout
)
except:
return False

return True


class NotificationsManager(gobject.GObject):
def __init__(self):
self.notify_interval = conf.notify_interval
self.minutes_passed = 0
self.notification = Notification()
gobject.timeout_add_seconds(60, self.check_interval)

def notify_interval_changed(self, value):
self.minutes_passed = 0
self.notify_interval = value

def check_interval(self):
if not conf.notifications_enabled:
self.minutes_passed = 0
return True

self.minutes_passed += 1

storage = hamster.client.Storage()
facts = storage.get_todays_facts()

if self.minutes_passed == self.notify_interval:
# if the activity is still active
if len(facts) > 0 and facts[-1].end_time is None:
timedelta_secs = (datetime.datetime.now() - facts[-1].start_time).seconds
hours, rem = divmod(timedelta_secs, 60 * 60)
minutes, seconds = divmod(rem, 60)
if hours != 0:
msg = str.format("Working on {} for {} hours and {} minutes", facts[-1].activity, hours, minutes)
else:
msg = str.format("Working on {} for {} minutes", facts[-1].activity, minutes)
self.notification.show(msg)
elif conf.notify_on_idle:
self.notification.show("No Activity")

self.minutes_passed = 0

return True

def send_test(self):
return self.notification.show("This is a test notification!")


notifs_mgr = NotificationsManager()
40 changes: 40 additions & 0 deletions src/hamster/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from hamster.lib import datetime as dt
from hamster.lib import stuff
from hamster.lib.configuration import Controller, runtime, conf
from hamster.lib.notifsmanager import notifs_mgr


def get_prev(selection, model):
Expand Down Expand Up @@ -133,11 +134,21 @@ def __init__(self):
(selection, selection.connect('changed', self.category_changed_cb, self.category_store))
])

# Tracking tab
self.day_start = widgets.TimeInput(dt.time(5,30))
self.get_widget("day_start_placeholder").add(self.day_start)

self.notify_scale = self.get_widget("notify-interval-scale")
self.notify_scale.set_range(1, 120)

self.notifs_enabled_toggle = self.get_widget("notifs-enabled-toggle")
self.notification_box = self.get_widget("notification-box")

self.load_config()

self.notify_scale.connect("value-changed", self._notify_interval_value_changed)
self.notifs_enabled_toggle.connect("toggled", self._on_notifications_toggled)

# Allow enable drag and drop of rows including row move
self.activity_tree.enable_model_drag_source(gdk.ModifierType.BUTTON1_MASK,
self.TARGETS,
Expand Down Expand Up @@ -174,6 +185,14 @@ def load_config(self, *args):
self.tags = [tag["name"] for tag in runtime.storage.get_tags(only_autocomplete=True)]
self.get_widget("autocomplete_tags").set_text(", ".join(self.tags))

# enable/disable notification related settings
self.notifs_enabled_toggle.set_active(conf.notifications_enabled)
self.notification_box.set_sensitive(conf.notifications_enabled)

self.notify_scale.set_value(conf.notify_interval)
self.get_widget("notify-on-idle").set_active(conf.notify_on_idle)


def on_autocomplete_tags_view_focus_out_event(self, view, event):
buf = self.get_widget("autocomplete_tags")
updated_tags = buf.get_text(buf.get_start_iter(), buf.get_end_iter(), 0)
Expand Down Expand Up @@ -509,3 +528,24 @@ def on_day_start_changed(self, widget):
conf.set("day-start-minutes", day_start)
def on_close_button_clicked(self, button):
self.close_window()

def _on_notifications_toggled(self, checkbox):
# TODO: Show error message next to the widget
# Test only if activated
if checkbox.get_active():
if notifs_mgr.send_test():
self.notification_box.set_sensitive(checkbox.get_active())
conf.set("notifications-enabled", checkbox.get_active())
else:
checkbox.set_active(False)

self.notification_box.set_sensitive(checkbox.get_active())
conf.set("notifications-enabled", checkbox.get_active())

def _notify_on_idle_toggled(self, checkbox):
conf.set("notify-on-idle-enabled", checkbox.get_active())

def _notify_interval_value_changed(self, range):
notify_interval = range.get_value()
conf.set("notify-interval-minutes", notify_interval)
notifs_mgr.notify_interval_changed(notify_interval)

0 comments on commit 88eb65f

Please sign in to comment.