-
Notifications
You must be signed in to change notification settings - Fork 18
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
[#136] Add 'recent activities' to tracking screen #208
base: develop
Are you sure you want to change the base?
Conversation
hamster_gtk/tracking/screens.py
Outdated
def _on_config_changed(self, sender): | ||
"""Callback triggered when 'config-changed' event fired.""" | ||
if self._app.config['tracking_show_recent_activities']: | ||
# We re-create it even if one existed before necause its parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
necause
@@ -80,6 +80,11 @@ def __init__(self, parent, app, initial, *args, **kwargs): | |||
('autocomplete_split_activity', | |||
(_("Autocomplete activities and categories separately"), | |||
HamsterSwitch())), | |||
('tracking_show_recent_activities', | |||
(_("Allow tracking based on recent activities."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not sound clear to me. I would choose something like “Show recent activities for quickly starting tracking”
hamster_gtk/helpers.py
Outdated
return OrderedSet(recent_activities) | ||
|
||
|
||
def serialize_activity(activity): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not we have something like this somewhere already?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think earlier hamster-lib
branches had something like this. Also the overview has its own "serialize activity" code which is different however:
- it deals with legacy hamerest representation of
activity.category=None
. This is something that I would be willing to throw out of the window. - It uses
-
as seperator betweenactivity.name
andcategory
. I think this is better looking for the overview. What do you think?
So this helper provides a generic serialization utilizing the standart @
seperator. As far as I can tell current versions of hamster-lib
or hamster-gtk
do not have such a function yet. But share the feeling that we had this around for a while in various incarnations...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Wait, do we intend to not support category-less facts?
- I actually prefer the at sign for consistency or habit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- No we do and want to support category less facts. I am not quite sure that the way legacy hamster did is really where we want to go..
- Does that mean you would prefer
@
in the overview as well? At this stage I do not care about this detail very much as we will have to revisit the general layout at some later stage anyway...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, having @
in overview is what I am accustomed to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alrighty. Will adjust this then :) Im cool either way tbh.
hamster_gtk/hamster_gtk.py
Outdated
@@ -279,6 +285,8 @@ def _get_default_config(self): | |||
# Frontend | |||
'autocomplete_activities_range': 30, | |||
'autocomplete_split_activity': False, | |||
'tracking_show_recent_activities': True, | |||
'tracking_recent_activities_items': 6, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use count
or number
. items
is less clear.
hamster_gtk/tracking/screens.py
Outdated
# allocated to its children so they actually have a height that we can | ||
# use. | ||
grid.show_all() | ||
# We fetch an arbitrary Button as height-reference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is really ugly and crashes when there are no items:
$ env XDG_CONFIG_HOME=$HOME/.dev_config XDG_DATA_HOME=$HOME/.dev_local hamster-gtk
Hamster-GTK started.
Traceback (most recent call last):
File "/nix/store/fzrxvdjas3icqb2n5akahvix758jnfvj-python3.6-hamster-gtk/lib/python3.6/site-packages/hamster_gtk/hamster_gtk.py", line 213, in _activate
self.window = MainWindow(app)
File "/nix/store/fzrxvdjas3icqb2n5akahvix758jnfvj-python3.6-hamster-gtk/lib/python3.6/site-packages/hamster_gtk/hamster_gtk.py", line 107, in __init__
self.add(TrackingScreen(self.app))
File "/nix/store/fzrxvdjas3icqb2n5akahvix758jnfvj-python3.6-hamster-gtk/lib/python3.6/site-packages/hamster_gtk/tracking/screens.py", line 49, in __init__
self.start_tracking_view = StartTrackingBox(self._app)
File "/nix/store/fzrxvdjas3icqb2n5akahvix758jnfvj-python3.6-hamster-gtk/lib/python3.6/site-packages/hamster_gtk/tracking/screens.py", line 195, in __init__
self.recent_activities_widget = self._get_recent_activities_widget()
File "/nix/store/fzrxvdjas3icqb2n5akahvix758jnfvj-python3.6-hamster-gtk/lib/python3.6/site-packages/hamster_gtk/tracking/screens.py", line 255, in _get_recent_activities_widget
child = grid.get_children()[1]
IndexError: list index out of range
Traceback (most recent call last):
File "/nix/store/fzrxvdjas3icqb2n5akahvix758jnfvj-python3.6-hamster-gtk/lib/python3.6/site-packages/hamster_gtk/hamster_gtk.py", line 218, in _activate
app.add_window(self.window)
TypeError: Argument 1 does not allow None as a value
Hamster-GTK shut down.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the way we derive our min_height hint is far from elegant (but fixed value layouts are far worse even). I am absolutely open to better approaches! Empty children are definitely a nice catch and have been addressed in the latest version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a todo comment and go with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created #224 as I would like to avoid todo comments.
hamster_gtk/tracking/screens.py
Outdated
|
||
def _populate(self): | ||
"""Fill the widget with rows per activity.""" | ||
def add_row_widgets(row_counter, activity): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
row_counter
→ row_index
/row_number
; counter implies an object that counts
hamster_gtk/helpers.py
Outdated
def get_recent_activities(controller, start, end): | ||
"""Return a list of all activities logged in facts within the given timeframe.""" | ||
recent_activities = [fact.activity for fact in controller.facts.get_all(start=start, end=end)] | ||
return OrderedSet(recent_activities) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The activities are returned in a convoluted order. It should be reversed prior to removing duplicates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I do understand. Could you elaborate please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be OrderedSet(reversed(recent_activities))
, otherwise you will get the activities in the order they were first used, not the last.
facts 1 2 1 3 2 1 3 output reversed
current x x x → 1 2 3 → 3 2 1
expected x x x → 3 1 2 → 2 1 3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the clarification. To be honest, right now FactManager.get_all()
does not commit to any ordering at all. I created an issue with hamster-lib
to improve this.
For now I will implement a workaround simple sorting call as part of the prelimery get_recent_activities
helper which will hopefully address your concerns.
hamster_gtk/tracking/screens.py
Outdated
|
||
today = datetime.date.today() | ||
start = today - datetime.timedelta(90) | ||
activities = reversed(helpers.get_recent_activities(self._controller, start, today)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really want all the activities and scroll instead of displaying the tracking_recent_activities_items
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer such a more general solution. There is nothing preventing us from limiting the results to just tracking_recent_activities_items
(via config) if we want, but especially given that we already have a solution I do not see the harm.
We need scrolling anyway (because we can not make any guarantee that tracking_recent_activities_items
will fit in the space available. In light of that, it seems we get the extra activities for free if the user bothers scolling.
What would be the downside?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accidental scrolling to the other end and performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- "accidental scrolling": Im not sure I see the use case. especially as there is the posibility of a scrollbox even if if we just fetch the number of activities defined in the config.
- by default we just fetch todays facts. this should net us no more than a couple of dozens facts at most I figure. I doubt there is any concievable performance impact on the DB or the GUI rendering. Unless I'm missing something this seems like a case of premature optimization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- You scroll somewhere accidentally and since the list is long you do not have a simple way of returning back – you cannot just quickly scroll down and when you find out that you are on the wrong side quickly scroll to the correct one.
- I see more than just today’s facts. In fact there does not seem to be any limit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right!
The idea was to make the timedelta adjustable via a config setting, but i forgot to actually do that :(
If done that way it is up to the user to figure what timeframe is viable to them. We probably should point out the performance consideration though...
It would probably be best to leave this additional customization to a seperate issue and use start=today
for now...
Closes: 206
This commits extends the 'start tracking' view with a list of recent activities that can be used to euther copy the data to the entry field, ready to be extended and then started manually by the user or to start/continue tracking this activity right away. Ref: #136
b41cbed
to
c17c7d4
Compare
c17c7d4
to
d941aab
Compare
Codecov Report
@@ Coverage Diff @@
## develop #208 +/- ##
===========================================
- Coverage 82.59% 80.21% -2.38%
===========================================
Files 31 31
Lines 1356 1456 +100
Branches 78 86 +8
===========================================
+ Hits 1120 1168 +48
- Misses 213 260 +47
- Partials 23 28 +5
Continue to review full report at Codecov.
|
hamster_gtk/tracking/screens.py
Outdated
@@ -45,7 +45,8 @@ def __init__(self, app, *args, **kwargs): | |||
self.set_transition_type(Gtk.StackTransitionType.SLIDE_UP) | |||
self.set_transition_duration(1000) | |||
self.current_fact_view = CurrentFactBox(self._app.controller) | |||
self.current_fact_view.connect('tracking-stopped', self.update) | |||
self.current_fact_view.con275G |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wah
b98097c
to
63762a9
Compare
aa0d45c
to
bec62d8
Compare
cd3947c
to
ddafbd1
Compare
Until now, we returned a ``PathLocal`` instance as value for the ``tmpfile_path`` key. This has been changed to a proper string representations instead.
Our ``app`` fixture (which is used extensively) used to instantiate the default ``HamsterGTK`` class. This meant that the default config loading was triggered and as a consequence the systems live config being used. This is obviously an issue. Instead we monkey patch the class now to skip the config loading machinery and use/return the ``config`` fixture.
Our previous test simply instantiated the class, hence tiggering the config loading/creation machinery. This will directly interfere with the actual user config! To avoid this we provide a new test that monkeypatches the class accordingly. As a consequence the config loading needs to be tested seperatly now though.
3fe166f
to
edbf341
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several typos, otherwise looks good from a shallow review (ignoring my bloat concerns)
tests/test_hamster-gtk.py
Outdated
app = hamster_gtk.HamsterGTK() | ||
def test_instantiation(self, config): | ||
""" | ||
Make sure class instatiation works as intended. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instatiation → instantiation
hamster_gtk/helpers.py
Outdated
separator (str, optional): ``string`` used to separate ``activity.name`` and | ||
``category.name``. The separator will be omitted if ``none_categoty=''`` and | ||
``activity.category=None``. Defaults to ``@``. | ||
none_category (str, optional): ``string`` to represent the 'lack of a cactegory' for an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cactegory
hamster_gtk/helpers.py
Outdated
def get_recent_activities(controller, start, end): | ||
"""Return a list of all activities logged in facts within the given timeframe.""" | ||
# [FIXME] | ||
# This manual sorting within python is of cause less than optimal. We stick |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
of cause → of course
hamster_gtk/helpers.py
Outdated
Args: | ||
activity (Activity): ``Activity`` instance to serialize. | ||
separator (str, optional): ``string`` used to separate ``activity.name`` and | ||
``category.name``. The separator will be omitted if ``none_categoty=''`` and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
none_categoty → none_category
tests/test_hamster-gtk.py
Outdated
|
||
We actually test against a monkeypatched class in order to avoid the | ||
config loading machinery as this would access the user data on fs. | ||
The relevant skiped methods need to be tested separately. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
skipped
hamster_gtk/tracking/screens.py
Outdated
# allocated to its children so they actually have a height that we can | ||
# use. | ||
grid.show_all() | ||
# We fetch an arbitrary Button as height-reference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a todo comment and go with this.
hamster_gtk/helpers.py
Outdated
return OrderedSet(recent_activities) | ||
|
||
|
||
def serialize_activity(activity, separator='@', none_category='not categorized'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch. 👍
When serializing facts for the 'continue tracking' functionality, we need to make sure that the 'uncategorized' placeholder is omitted, otherwise a category of that name would be created! Ref.: #136
hamster_gtk/tracking/screens.py
Outdated
""" | ||
def get_label(activity): | ||
"""Label representing the activity/category combination.""" | ||
label = Gtk.Label(helpers.serialize_activity(activity, none_category='')) |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
a2f4df4
to
a33d84c
Compare
This adds a 'recent activities' area to the tracking screen that can be used to take previous activities as templates for new raw fact strings or start tracking them right away. The entire functionality is optional (on by default right now) and can be configures via preferences.
The 'recent activities' box size can be adjusted by specifying the amount of activities it shall be able to show. All activities that not fit are available via scrolling.
Closes: #136