Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Associate tasks to specific workspaces and follow changes automatically #259

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion src/hamster/lib/desktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@


from hamster import idle
from hamster import workspace
from hamster.lib.configuration import conf
from hamster.lib import trophies
import dbus
Expand All @@ -33,6 +34,7 @@ class DesktopIntegrations(object):
def __init__(self, storage):
self.storage = storage # can't use client as then we get in a dbus loop
self._last_notification = None
self._saved = {}

dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
self.bus = dbus.SessionBus()
Expand All @@ -47,6 +49,10 @@ def __init__(self, storage):

gobject.timeout_add_seconds(60, self.check_hamster)

self.use_workspace_changes = True # TODO: should be a proper setting
self.workspace_listener = workspace.WnckWatcher()
self.workspace_listener.connect('workspace-changed', self.on_workspace_changed)


def check_hamster(self):
"""refresh hamster every x secs - load today, check last activity etc."""
Expand Down Expand Up @@ -108,13 +114,66 @@ def notify_user(self, summary="", details=""):


def on_idle_changed(self, event, state):
if not self.conf_enable_timeout:
if '__paused__' in self._saved:
del self._saved['__paused__']
return

# state values: 0 = active, 1 = idle
if state == 1 and self.conf_enable_timeout:
if state == 1:
idle_from = self.idle_listener.getIdleFrom()
idle_from = timegm(idle_from.timetuple())
self.save_current('__paused__')
self.storage.StopTracking(idle_from)
elif '__paused__' in self._saved:
self.restore('__paused__', delete=True)


def on_workspace_changed(self, event, previous_workspace, current_workspace):
if not self.use_workspace_changes:
return

if previous_workspace is not None:
self.save_current( previous_workspace )
self.restore(current_workspace)


def on_conf_changed(self, event, key, value):
if hasattr(self, "conf_%s" % key):
setattr(self, "conf_%s" % key, value)


def get_current(self):
facts = self.storage.get_todays_facts()
if facts:
last = facts[-1]
if not last['end_time']:
name = last['name']
category = last['category']
return name,category
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this should also include tags and other metadata, basically the whole Fact instance.



def save_current(self, key):
current = self.get_current()
if current is not None:
self._saved[key] = current
elif key in self._saved:
del self._saved[key]


def restore(self, key, delete=False):
activity,category = None,None
if key in self._saved:
activity, category = self._saved[key]
if delete:
del self._saved[key]

if not activity:
self.storage.StopTracking(None)
return

if category:
activity = '%s@%s' % (activity,category)

self.storage.add_fact( activity, None, None)

51 changes: 51 additions & 0 deletions src/hamster/workspace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# - coding: utf-8 -

# Copyright (C) 2015 Aurelien Naldi <aurelien.naldi at 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/>.

from gi.repository import GObject as gobject
from gi.repository import Wnck as wnck
import dbus

class WnckWatcher(gobject.GObject):
"""
Listen for workspace changes with Wnck and forward them to the desktop integration agent.
It handles all wnck-specific parts and forwards standardised signals, based on the screensaver helper.
"""
__gsignals__ = {
"workspace-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,gobject.TYPE_PYOBJECT))
}
def __init__(self):
gobject.GObject.__init__(self)

try:
self.bus = dbus.SessionBus()
except:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please only catch the specific exceptions you expect.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I'm not familiar with dbus, I copied this from idle.py, but all other places in hamster where a session bus is retrieved are unprotected, so I'm taking out the try/except here.

return 0
wnck.Screen.get_default().connect("active-workspace-changed", self.on_workspace_changed)


def on_workspace_changed(self, screen, previous_workspace):
try:
workspace_id = screen.get_active_workspace().get_number()
if previous_workspace:
previous_workspace = previous_workspace.get_number()
except:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'm not so sure about what could go wrong, I guess the main source of actual problem is at import time: if wnck is missing. I will also remove this try/catch
On a related note, I wonder what will happen to wnck in a wayland world.

return

self.emit('workspace-changed', previous_workspace, workspace_id)