NowFocus 0.2.5__tar.gz → 0.2.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nowfocus-0.2.5/src/nowfocus.egg-info → nowfocus-0.2.7}/PKG-INFO +18 -18
- {nowfocus-0.2.5 → nowfocus-0.2.7}/README.md +17 -17
- {nowfocus-0.2.5 → nowfocus-0.2.7}/pyproject.toml +1 -1
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/__main__.py +6 -5
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/trello.py +6 -6
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/settings.py +3 -3
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/task_window.py +131 -92
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/utils.py +5 -3
- {nowfocus-0.2.5 → nowfocus-0.2.7/src/nowfocus.egg-info}/PKG-INFO +18 -18
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus.egg-info/SOURCES.txt +4 -4
- nowfocus-0.2.7/src/nowfocus.egg-info/top_level.txt +1 -0
- nowfocus-0.2.5/src/nowfocus.egg-info/top_level.txt +0 -2
- {nowfocus-0.2.5 → nowfocus-0.2.7}/LICENSE +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/setup.cfg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/__init__.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/conf.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/activitywatch.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/caldav.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/csv.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/psc_timetracker.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/taskwarrior.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/timewarrior.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/todo_template.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/todotxt.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/txt.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/connectors/vikunja.py +0 -0
- {nowfocus-0.2.5/src → nowfocus-0.2.7/src/nowfocus}/desktop-extras/nowfocus.desktop +0 -0
- {nowfocus-0.2.5/src → nowfocus-0.2.7/src/nowfocus}/desktop-extras/nowfocus.png +0 -0
- {nowfocus-0.2.5/src → nowfocus-0.2.7/src/nowfocus}/desktop-extras/nowfocus.svg +0 -0
- {nowfocus-0.2.5/src → nowfocus-0.2.7/src/nowfocus}/desktop-extras/set_gsettings_keybinding.sh +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/example-todo.txt +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/cancel.png +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/cancel.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/edit.png +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/edit.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-0.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-1.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-2.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-3.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-4.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-5.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-6.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-7.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-8.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon-9.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/icon.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/mark-done.png +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/mark-done.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/pause.png +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/pause.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/settings.png +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/icon/settings.svg +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/new_task_dialog.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/session_edit_dialog.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/session_options.py +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/sessions.csv +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/sound/bell-xylophone-g.mp3 +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/sound/dinner-bell.mp3 +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/sound/xylophone-chord.mp3 +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus/styles.css +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus.egg-info/dependency_links.txt +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus.egg-info/entry_points.txt +0 -0
- {nowfocus-0.2.5 → nowfocus-0.2.7}/src/nowfocus.egg-info/requires.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nowfocus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: nowfocus: the open source task-tracking self-control panel.
|
|
5
5
|
Author: GitFr33
|
|
6
6
|
Project-URL: Homepage, https://gitlab.com/GitFr33/nowfocus
|
|
@@ -92,40 +92,37 @@ nowfocus is a clean, keyboard-driven project time tracker build with python + GT
|
|
|
92
92
|
- [TimeWarrior](https://timewarrior.net)
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
## Installation
|
|
95
|
+
## Installation
|
|
96
96
|
|
|
97
|
-
Run the following in terminal to install and setup:
|
|
97
|
+
1. Run the following in terminal to install and setup:
|
|
98
98
|
```
|
|
99
99
|
# Install dependencies
|
|
100
|
-
sudo apt install
|
|
100
|
+
sudo apt install pipx gir1.2-appindicator3-0.1 meson libdbus-glib-1-dev patchelf libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev
|
|
101
101
|
|
|
102
102
|
# Set up pipx
|
|
103
103
|
pipx ensurepath
|
|
104
104
|
|
|
105
|
+
# At this point you may need to restart your terminal window
|
|
106
|
+
|
|
105
107
|
# Install nowfocus
|
|
106
108
|
pipx install nowfocus
|
|
107
109
|
|
|
108
110
|
# Enter application directory
|
|
109
|
-
cd ~/.local/pipx/nowfocus
|
|
110
|
-
|
|
111
|
-
# Copy .desktop and icon to .local/share
|
|
112
|
-
cp src/desktop-extras/nowfocus.desktop ~/.local/share/applications/nowfocus.desktop
|
|
113
|
-
cp src/desktop-extras/nowfocus.svg ~/.local/share/icons/nowfocus.png
|
|
114
|
-
cp src/desktop-extras/nowfocus.svg ~/.local/share/icons/hicolor/scalable/apps/nowfocus.svg
|
|
115
|
-
|
|
116
|
-
# Setup autostart
|
|
117
|
-
cp src/desktop-extras/nowfocus.desktop ~/.config/autostart/nowfocus.desktop
|
|
111
|
+
cd ~/.local/share/pipx/venvs/nowfocus/lib/python3.12/site-packages/nowfocus/desktop-extras
|
|
118
112
|
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
src/desktop-extras/set_gsettings_keybinding.sh "Open nowfocus" nowfocus "<Super>space"
|
|
113
|
+
# Copy .desktop and icon to /usr/share
|
|
114
|
+
sudo cp nowfocus.desktop /usr/share/applications/nowfocus.desktop
|
|
115
|
+
sudo cp nowfocus.svg /usr/share/icons/hicolor/scalable/apps/nowfocus.svg
|
|
123
116
|
|
|
124
117
|
# and now Focus!
|
|
125
118
|
nowfocus
|
|
126
119
|
|
|
127
120
|
```
|
|
128
121
|
|
|
122
|
+
2. Set up a keybinding (on Ubuntu or Linux Mint), open **Settings > Keyboard > Keyboard Shortcuts > Custom Shortcuts**, set the **command** to `nowfocus`, and pick whatever key combo you'd like.
|
|
123
|
+
|
|
124
|
+
3. Add the following command to your startup applications: `nowfocus --force`
|
|
125
|
+
|
|
129
126
|
|
|
130
127
|
|
|
131
128
|
## Usage
|
|
@@ -138,7 +135,10 @@ Open nowfocus **Settings** from the indicator menu or tasks window and connect y
|
|
|
138
135
|
|
|
139
136
|
- `F11` Toggle fullscreen
|
|
140
137
|
- `Esc` Close task window
|
|
141
|
-
- `Enter` Start top task (or make a new task with current search phrase if no results)
|
|
138
|
+
- `Enter` Start top/selected task (or make a new task with current search phrase if no results)
|
|
139
|
+
- `Shift Enter` or `Shift Click` Transfer current session time to selected task (or top task if none selected)
|
|
140
|
+
- `Control Enter` or `Control Click` show opetions menu for selected (or top) task
|
|
141
|
+
- `Alt Enter` or `Alt Click` Open todolist for selected (or top) task
|
|
142
142
|
- `Ctrl + P` **Pause** current task
|
|
143
143
|
- `Ctrl + D` Pause current task and mark it **Done**
|
|
144
144
|
- `Ctrl + X` Cancel current task
|
|
@@ -46,40 +46,37 @@ nowfocus is a clean, keyboard-driven project time tracker build with python + GT
|
|
|
46
46
|
- [TimeWarrior](https://timewarrior.net)
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
## Installation
|
|
49
|
+
## Installation
|
|
50
50
|
|
|
51
|
-
Run the following in terminal to install and setup:
|
|
51
|
+
1. Run the following in terminal to install and setup:
|
|
52
52
|
```
|
|
53
53
|
# Install dependencies
|
|
54
|
-
sudo apt install
|
|
54
|
+
sudo apt install pipx gir1.2-appindicator3-0.1 meson libdbus-glib-1-dev patchelf libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev
|
|
55
55
|
|
|
56
56
|
# Set up pipx
|
|
57
57
|
pipx ensurepath
|
|
58
58
|
|
|
59
|
+
# At this point you may need to restart your terminal window
|
|
60
|
+
|
|
59
61
|
# Install nowfocus
|
|
60
62
|
pipx install nowfocus
|
|
61
63
|
|
|
62
64
|
# Enter application directory
|
|
63
|
-
cd ~/.local/pipx/nowfocus
|
|
64
|
-
|
|
65
|
-
# Copy .desktop and icon to .local/share
|
|
66
|
-
cp src/desktop-extras/nowfocus.desktop ~/.local/share/applications/nowfocus.desktop
|
|
67
|
-
cp src/desktop-extras/nowfocus.svg ~/.local/share/icons/nowfocus.png
|
|
68
|
-
cp src/desktop-extras/nowfocus.svg ~/.local/share/icons/hicolor/scalable/apps/nowfocus.svg
|
|
69
|
-
|
|
70
|
-
# Setup autostart
|
|
71
|
-
cp src/desktop-extras/nowfocus.desktop ~/.config/autostart/nowfocus.desktop
|
|
65
|
+
cd ~/.local/share/pipx/venvs/nowfocus/lib/python3.12/site-packages/nowfocus/desktop-extras
|
|
72
66
|
|
|
73
|
-
#
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
src/desktop-extras/set_gsettings_keybinding.sh "Open nowfocus" nowfocus "<Super>space"
|
|
67
|
+
# Copy .desktop and icon to /usr/share
|
|
68
|
+
sudo cp nowfocus.desktop /usr/share/applications/nowfocus.desktop
|
|
69
|
+
sudo cp nowfocus.svg /usr/share/icons/hicolor/scalable/apps/nowfocus.svg
|
|
77
70
|
|
|
78
71
|
# and now Focus!
|
|
79
72
|
nowfocus
|
|
80
73
|
|
|
81
74
|
```
|
|
82
75
|
|
|
76
|
+
2. Set up a keybinding (on Ubuntu or Linux Mint), open **Settings > Keyboard > Keyboard Shortcuts > Custom Shortcuts**, set the **command** to `nowfocus`, and pick whatever key combo you'd like.
|
|
77
|
+
|
|
78
|
+
3. Add the following command to your startup applications: `nowfocus --force`
|
|
79
|
+
|
|
83
80
|
|
|
84
81
|
|
|
85
82
|
## Usage
|
|
@@ -92,7 +89,10 @@ Open nowfocus **Settings** from the indicator menu or tasks window and connect y
|
|
|
92
89
|
|
|
93
90
|
- `F11` Toggle fullscreen
|
|
94
91
|
- `Esc` Close task window
|
|
95
|
-
- `Enter` Start top task (or make a new task with current search phrase if no results)
|
|
92
|
+
- `Enter` Start top/selected task (or make a new task with current search phrase if no results)
|
|
93
|
+
- `Shift Enter` or `Shift Click` Transfer current session time to selected task (or top task if none selected)
|
|
94
|
+
- `Control Enter` or `Control Click` show opetions menu for selected (or top) task
|
|
95
|
+
- `Alt Enter` or `Alt Click` Open todolist for selected (or top) task
|
|
96
96
|
- `Ctrl + P` **Pause** current task
|
|
97
97
|
- `Ctrl + D` Pause current task and mark it **Done**
|
|
98
98
|
- `Ctrl + X` Cancel current task
|
|
@@ -156,8 +156,8 @@ class Application(Gtk.Application):
|
|
|
156
156
|
|
|
157
157
|
def quit(self, widget_or_signal_source=None, condition=None):
|
|
158
158
|
print("Adios ", conf.app_name)
|
|
159
|
-
print("widget_or_signal_source ", widget_or_signal_source)
|
|
160
|
-
print("condition ", condition)
|
|
159
|
+
# print("widget_or_signal_source ", widget_or_signal_source)
|
|
160
|
+
# print("condition ", condition)
|
|
161
161
|
|
|
162
162
|
if self.is_running:
|
|
163
163
|
print('Caching active session', self.session['label'])
|
|
@@ -484,7 +484,7 @@ class Application(Gtk.Application):
|
|
|
484
484
|
self.mark_done(None,task)
|
|
485
485
|
|
|
486
486
|
else:
|
|
487
|
-
print("add ",utils.extended_label(task)," to recent tasks")
|
|
487
|
+
# print("add ",utils.extended_label(task)," to recent tasks")
|
|
488
488
|
i = Gtk.MenuItem.new_with_label(utils.extended_label(task))
|
|
489
489
|
i.connect('activate',self.start_task,task)
|
|
490
490
|
list_menus['recent'].prepend(i)
|
|
@@ -511,8 +511,9 @@ class Application(Gtk.Application):
|
|
|
511
511
|
|
|
512
512
|
self.is_running = False
|
|
513
513
|
# print(utils.get_times(task))
|
|
514
|
-
|
|
515
|
-
|
|
514
|
+
if action != 'cancel':
|
|
515
|
+
notify.Notification.new("Focused on "+session['label']+" for "+sec_to_time(session['duration']),utils.pretty_dict(utils.get_times(task)), None).show()
|
|
516
|
+
# notify.Notification.new(action.capitalize()+" "+session['label']+" "+sec_to_time(session['duration']),utils.pretty_dict(utils.get_times(task)), None).show()
|
|
516
517
|
|
|
517
518
|
# Start randomness timer
|
|
518
519
|
self.session = {
|
|
@@ -57,8 +57,8 @@ def get_todos(user_conf):
|
|
|
57
57
|
|
|
58
58
|
for board in boards:
|
|
59
59
|
|
|
60
|
-
print("\n\n--- Board --- \n")
|
|
61
|
-
pretty_print(board)
|
|
60
|
+
# print("\n\n--- Board --- \n")
|
|
61
|
+
# pretty_print(board)
|
|
62
62
|
|
|
63
63
|
if board['closed']:
|
|
64
64
|
continue
|
|
@@ -80,8 +80,8 @@ def get_todos(user_conf):
|
|
|
80
80
|
|
|
81
81
|
for bucket in board['lists']:
|
|
82
82
|
|
|
83
|
-
print("\n\n--- bucket --- \n")
|
|
84
|
-
pretty_print(bucket)
|
|
83
|
+
# print("\n\n--- bucket --- \n")
|
|
84
|
+
# pretty_print(bucket)
|
|
85
85
|
|
|
86
86
|
if bucket['closed']:
|
|
87
87
|
continue
|
|
@@ -216,8 +216,8 @@ def mark_task_done(task):
|
|
|
216
216
|
params=query
|
|
217
217
|
)
|
|
218
218
|
|
|
219
|
-
print("response.text")
|
|
220
|
-
print(response.text)
|
|
219
|
+
# print("response.text")
|
|
220
|
+
# print(response.text)
|
|
221
221
|
|
|
222
222
|
return response.text
|
|
223
223
|
|
|
@@ -105,8 +105,8 @@ class SettingsWindow(Gtk.Window):
|
|
|
105
105
|
|
|
106
106
|
def scroll_box(self, parent_widget = None, height = 300):
|
|
107
107
|
|
|
108
|
-
print('parent_widget')
|
|
109
|
-
print(parent_widget)
|
|
108
|
+
# print('parent_widget')
|
|
109
|
+
# print(parent_widget)
|
|
110
110
|
|
|
111
111
|
scrolled_window = Gtk.ScrolledWindow()
|
|
112
112
|
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
|
@@ -744,7 +744,7 @@ class EditAddTargetDialog(Gtk.Dialog):
|
|
|
744
744
|
|
|
745
745
|
super().__init__(title="Set Time Target", transient_for=parent, flags=0)
|
|
746
746
|
|
|
747
|
-
self.set_default_size(
|
|
747
|
+
self.set_default_size(700,850)
|
|
748
748
|
self.set_border_width(15)
|
|
749
749
|
box = self.get_content_area()
|
|
750
750
|
box.set_spacing(15)
|
|
@@ -15,7 +15,7 @@ class TaskWindow(Gtk.Window):
|
|
|
15
15
|
Gdk.Screen.get_default(), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
16
16
|
)
|
|
17
17
|
_instance = None
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
def __init__(self,app,passed_data=None):
|
|
20
20
|
|
|
21
21
|
if TaskWindow._instance:
|
|
@@ -39,7 +39,12 @@ class TaskWindow(Gtk.Window):
|
|
|
39
39
|
|
|
40
40
|
Gtk.Window.__init__(self, title=conf.app_name)
|
|
41
41
|
|
|
42
|
-
self.set_default_size(900,
|
|
42
|
+
self.set_default_size(900,900)
|
|
43
|
+
self.modifyer_keys = {
|
|
44
|
+
'control': False,
|
|
45
|
+
'shift': False,
|
|
46
|
+
'alt': False,
|
|
47
|
+
}
|
|
43
48
|
|
|
44
49
|
self.search_cache_refresh_time = now().strftime("%Y-%m-%d %H:%M:%S")
|
|
45
50
|
self.search_cache = {}
|
|
@@ -126,7 +131,7 @@ class TaskWindow(Gtk.Window):
|
|
|
126
131
|
self.scrolled_window = Gtk.ScrolledWindow()
|
|
127
132
|
self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
|
128
133
|
box.pack_start(self.scrolled_window, True, True, 0)
|
|
129
|
-
self.scrolled_window.set_size_request(-1,
|
|
134
|
+
self.scrolled_window.set_size_request(-1, 350)
|
|
130
135
|
|
|
131
136
|
self.scrolled_window.connect('scroll-event', self.on_scroll) # This doesn't catch scrollbar moves
|
|
132
137
|
self.scrolled_window.connect('edge-reached', self.on_scroll) # This is a little late
|
|
@@ -194,11 +199,8 @@ class TaskWindow(Gtk.Window):
|
|
|
194
199
|
except Exception as e:
|
|
195
200
|
dbg("error adding todo connector open() to task window ",e, s='taskwindow')
|
|
196
201
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
202
|
self.new_task_button = Gtk.Button(label="New Task")
|
|
201
|
-
self.new_task_button.set_property("tooltip-text","Add a new task
|
|
203
|
+
self.new_task_button.set_property("tooltip-text","Add a new task (Ctrl + N)")
|
|
202
204
|
self.new_task_button.connect("clicked",self.open_new_task_dialog)
|
|
203
205
|
self.buttons_box.add(self.new_task_button)
|
|
204
206
|
|
|
@@ -210,7 +212,8 @@ class TaskWindow(Gtk.Window):
|
|
|
210
212
|
key, mod = Gtk.accelerator_parse('<Control>r')
|
|
211
213
|
self.refresh_button.add_accelerator("clicked", self.accel_group, key, mod, Gtk.AccelFlags.VISIBLE)
|
|
212
214
|
|
|
213
|
-
self.connect("key-press-event", self.
|
|
215
|
+
self.connect("key-press-event", self.key_press)
|
|
216
|
+
self.connect('key-release-event', self.key_release)
|
|
214
217
|
self.connect("window-state-event", self.on_window_state_event)
|
|
215
218
|
|
|
216
219
|
self.taskEntry.connect("changed",self.task_search)
|
|
@@ -409,7 +412,6 @@ class TaskWindow(Gtk.Window):
|
|
|
409
412
|
|
|
410
413
|
|
|
411
414
|
|
|
412
|
-
|
|
413
415
|
def add_task_to_list(self,t):
|
|
414
416
|
|
|
415
417
|
try:
|
|
@@ -423,7 +425,6 @@ class TaskWindow(Gtk.Window):
|
|
|
423
425
|
|
|
424
426
|
label = Gtk.Label()
|
|
425
427
|
|
|
426
|
-
# self.shown_tasks[t['id']].set_label(label)
|
|
427
428
|
# button_context = self.shown_tasks[t['id']].get_style_context().add_class("large")
|
|
428
429
|
extended_label = GLib.markup_escape_text(t['extended_label'],)
|
|
429
430
|
|
|
@@ -434,6 +435,7 @@ class TaskWindow(Gtk.Window):
|
|
|
434
435
|
|
|
435
436
|
extended_label = extended_label.replace(search_str,"<b>"+search_str+"</b>")
|
|
436
437
|
extended_label = extended_label.replace(search_str.capitalize(),"<b>"+search_str.capitalize()+"</b>") # Cheesy
|
|
438
|
+
|
|
437
439
|
if "duration" in t and t['duration']:
|
|
438
440
|
extended_label += " ("+sec_to_time(t['duration'])+")"
|
|
439
441
|
|
|
@@ -443,14 +445,12 @@ class TaskWindow(Gtk.Window):
|
|
|
443
445
|
if t['priority']:
|
|
444
446
|
extended_label = str(t['priority']) +" "+ extended_label
|
|
445
447
|
|
|
446
|
-
|
|
447
448
|
if not t['status']:
|
|
448
|
-
utils.dbg("add strikethrough to done task "+t['extended_label'],l=3,s="taskwindow")
|
|
449
|
+
# utils.dbg("add strikethrough to done task "+t['extended_label'],l=3,s="taskwindow")
|
|
449
450
|
# button_context.add_class("done")
|
|
450
451
|
label.set_markup('<s>'+extended_label+'</s>')
|
|
451
452
|
|
|
452
453
|
elif t['priority'] > 0:
|
|
453
|
-
# button_context.add_class("bold")
|
|
454
454
|
label.set_name('priorityTask')
|
|
455
455
|
label.set_markup(extended_label)
|
|
456
456
|
else:
|
|
@@ -471,83 +471,90 @@ class TaskWindow(Gtk.Window):
|
|
|
471
471
|
|
|
472
472
|
|
|
473
473
|
def select_task(self,widget,event=None,tid=None):
|
|
474
|
+
print("select_task task id",tid)
|
|
474
475
|
t = utils.db_get_item_by_id(tid)
|
|
475
|
-
print('event',event)
|
|
476
|
-
|
|
476
|
+
# print('event',event)
|
|
477
|
+
print("select_task self.modifyer_keys", self.modifyer_keys)
|
|
477
478
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
479
|
+
if self.modifyer_keys['control'] or event and event.button == 3: # Right-click (button 3) or control click context menu popover
|
|
480
|
+
|
|
481
|
+
popover = self.task_rclick_menu
|
|
482
|
+
widget.set_popover(popover)
|
|
482
483
|
|
|
483
|
-
|
|
484
|
+
popover.foreach(lambda child: child.destroy())
|
|
484
485
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
else:
|
|
527
|
-
disabled = ""
|
|
528
|
-
|
|
529
|
-
w = Gtk.Button(label="Edit Command: '"+command_data['command']+"' "+disabled+"")
|
|
486
|
+
vbox = Gtk.Box(spacing=0, orientation=Gtk.Orientation.VERTICAL)
|
|
487
|
+
vbox.set_border_width(5)
|
|
488
|
+
|
|
489
|
+
# Open todo
|
|
490
|
+
w = Gtk.Button(label="Open in "+conf.user['todolists'][t['todolist']]['label'])
|
|
491
|
+
w.set_halign(Gtk.Align.START)
|
|
492
|
+
w.set_relief(Gtk.ReliefStyle.NONE)
|
|
493
|
+
w.connect('clicked',utils.open_todo,t)
|
|
494
|
+
vbox.pack_start(w, True, True, 5)
|
|
495
|
+
|
|
496
|
+
# mark_done
|
|
497
|
+
w = Gtk.Button(label="Mark done")
|
|
498
|
+
w.set_halign(Gtk.Align.START)
|
|
499
|
+
w.set_relief(Gtk.ReliefStyle.NONE)
|
|
500
|
+
w.connect('clicked',self.app.mark_done,t)
|
|
501
|
+
vbox.pack_start(w, True, True, 5)
|
|
502
|
+
|
|
503
|
+
# Reassign session/randomness to be on this task,
|
|
504
|
+
w = Gtk.Button(label="Reassign last "+ str(round((self.app.session['duration'] / 60),1))+" minutes to this task" )
|
|
505
|
+
w.set_halign(Gtk.Align.START)
|
|
506
|
+
w.set_relief(Gtk.ReliefStyle.NONE)
|
|
507
|
+
w.connect('clicked',self.app.start_task,t,True)
|
|
508
|
+
vbox.pack_start(w, True, True, 5)
|
|
509
|
+
|
|
510
|
+
# show/edit targets
|
|
511
|
+
ttt_data = utils.get_time_target_data(t)
|
|
512
|
+
if ttt_data:
|
|
513
|
+
w = Gtk.Button(label="Edit Target:"+str(ttt_data['type'])+ " "+str(round(ttt_data['value']))+" minutes per "+str(round(ttt_data['within_value']))+" "+str(ttt_data['within_unit'])+" ("+str(round(utils.check_time_target(t)))+" minutes remaining)")
|
|
514
|
+
else:
|
|
515
|
+
w = Gtk.Button(label="Set Time Target")
|
|
516
|
+
w.set_halign(Gtk.Align.START)
|
|
517
|
+
w.set_relief(Gtk.ReliefStyle.NONE)
|
|
518
|
+
w.connect('clicked', lambda button_widget: EditAddTargetDialog(self,'tasks', t['id']))
|
|
519
|
+
vbox.pack_start(w, True, True, 5)
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
# show/edit commands
|
|
523
|
+
if t['id'] in conf.user['task_commands']:
|
|
524
|
+
command_data = conf.user['task_commands'][t['id']]
|
|
525
|
+
if not command_data['status']:
|
|
526
|
+
disabled = "(disabled)"
|
|
530
527
|
else:
|
|
531
|
-
|
|
528
|
+
disabled = ""
|
|
532
529
|
|
|
533
|
-
w.
|
|
534
|
-
|
|
535
|
-
w
|
|
536
|
-
vbox.pack_start(w, True, True, 5)
|
|
530
|
+
w = Gtk.Button(label="Edit Command: '"+command_data['command']+"' "+disabled+"")
|
|
531
|
+
else:
|
|
532
|
+
w = Gtk.Button(label="Add Task Command")
|
|
537
533
|
|
|
534
|
+
w.set_halign(Gtk.Align.START)
|
|
535
|
+
w.set_relief(Gtk.ReliefStyle.NONE)
|
|
536
|
+
w.connect('clicked', lambda button_widget: EditTaskCommandDialog(None, self, t['id']))
|
|
537
|
+
vbox.pack_start(w, True, True, 5)
|
|
538
538
|
|
|
539
|
-
# get_times, Ugly
|
|
540
|
-
# for key, val in utils.get_times(t).items():
|
|
541
|
-
# vbox.pack_start(Gtk.Label(key+": "+val), True, True, 5)
|
|
542
539
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
540
|
+
# get_times, Ugly
|
|
541
|
+
# for key, val in utils.get_times(t).items():
|
|
542
|
+
# vbox.pack_start(Gtk.Label(key+": "+val), True, True, 5)
|
|
546
543
|
|
|
547
|
-
|
|
544
|
+
popover.add(vbox)
|
|
545
|
+
popover.set_position(Gtk.PositionType.BOTTOM)
|
|
546
|
+
popover.show_all()
|
|
548
547
|
|
|
548
|
+
return
|
|
549
549
|
|
|
550
|
-
self.
|
|
550
|
+
if self.modifyer_keys['shift']:
|
|
551
|
+
print('transfer session')
|
|
552
|
+
self.app.start_task(None,t,True)
|
|
553
|
+
elif self.modifyer_keys['alt']:
|
|
554
|
+
print('open_todo')
|
|
555
|
+
utils.open_todo(None,t)
|
|
556
|
+
else:
|
|
557
|
+
self.app.start_task(None,t)
|
|
551
558
|
|
|
552
559
|
self.destroy()
|
|
553
560
|
|
|
@@ -596,29 +603,61 @@ class TaskWindow(Gtk.Window):
|
|
|
596
603
|
utils.save_user_settings()
|
|
597
604
|
|
|
598
605
|
|
|
599
|
-
def
|
|
606
|
+
def key_release(self, widget, event):
|
|
607
|
+
key = Gdk.keyval_name(event.keyval)
|
|
608
|
+
# utils.dbg("key_release",key,s="taskwindow",l=1)
|
|
609
|
+
# utils.dbg("key_release event.state",event.state,s="taskwindow",l=1)
|
|
610
|
+
if (event.state & Gdk.ModifierType.CONTROL_MASK):
|
|
611
|
+
self.modifyer_keys['control'] = False
|
|
612
|
+
if (event.state & Gdk.ModifierType.SHIFT_MASK):
|
|
613
|
+
self.modifyer_keys['shift'] = False
|
|
614
|
+
if (event.state & Gdk.ModifierType.MOD1_MASK):
|
|
615
|
+
self.modifyer_keys['alt'] = False
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
# print("modifyer_keys",self.modifyer_keys)
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def key_press(self, widget, event):
|
|
600
622
|
|
|
601
|
-
key = Gdk.keyval_name(
|
|
602
|
-
utils.dbg("
|
|
603
|
-
# utils.dbg("
|
|
604
|
-
utils.dbg("
|
|
623
|
+
key = Gdk.keyval_name(event.keyval)
|
|
624
|
+
# utils.dbg("key_press",key,s="taskwindow",l=1)
|
|
625
|
+
# utils.dbg("key_press event.state",event.state,s="taskwindow",l=1)
|
|
626
|
+
# utils.dbg("key_press_event",event,s="taskwindow",l=1)
|
|
627
|
+
# utils.dbg("ModifierType is CONTROL_MASK",Gdk.ModifierType.CONTROL_MASK,s="taskwindow",l=3)
|
|
605
628
|
|
|
629
|
+
if (event.state & Gdk.ModifierType.CONTROL_MASK) or key == 'Control_L':
|
|
630
|
+
self.modifyer_keys['control'] = True
|
|
631
|
+
if (event.state & Gdk.ModifierType.SHIFT_MASK) or key == 'Shift_L':
|
|
632
|
+
self.modifyer_keys['shift'] = True
|
|
633
|
+
if (event.state & Gdk.ModifierType.MOD1_MASK) or key == 'Alt_L':
|
|
634
|
+
self.modifyer_keys['alt'] = True
|
|
635
|
+
|
|
636
|
+
# print("modifyer_keys", self.modifyer_keys)
|
|
637
|
+
|
|
606
638
|
|
|
607
639
|
if key == "F11":
|
|
608
640
|
self.toggle_fullscreen()
|
|
609
641
|
elif key == "Escape":
|
|
610
642
|
self.destroy()
|
|
611
|
-
elif key in ['l','f'] and Gdk.ModifierType.CONTROL_MASK and not self.taskEntry.is_focus():
|
|
643
|
+
elif key in ['l','f'] and (event.state & Gdk.ModifierType.CONTROL_MASK) and not self.taskEntry.is_focus():
|
|
612
644
|
self.taskEntry.grab_focus()
|
|
613
645
|
|
|
614
|
-
elif key == "Return"
|
|
615
|
-
# print(
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
self.
|
|
646
|
+
elif key == "Return":
|
|
647
|
+
# print('self.get_focus()',self.get_focus())
|
|
648
|
+
# print('self.tasks_box.get_children()[1]',self.tasks_box.get_children()[1])
|
|
649
|
+
if self.taskEntry.is_focus():
|
|
650
|
+
# print("self.taskEntry has focus, do the thing")
|
|
651
|
+
if self.shown_tasks:
|
|
652
|
+
self.tasks_box.get_children()[0].emit('activate')
|
|
653
|
+
else:
|
|
654
|
+
self.new_task_button.emit('clicked')
|
|
655
|
+
|
|
656
|
+
elif self.shown_tasks and self.get_focus() in self.tasks_box.get_children():
|
|
657
|
+
# print("Return pressed on shown task select it",self.get_focus())
|
|
658
|
+
self.get_focus().emit('activate')
|
|
620
659
|
|
|
621
660
|
|
|
622
|
-
def on_window_state_event(self, widget,
|
|
623
|
-
self.__is_fullscreen = bool(
|
|
661
|
+
def on_window_state_event(self, widget, event):
|
|
662
|
+
self.__is_fullscreen = bool(event.new_window_state & Gdk.WindowState.FULLSCREEN)
|
|
624
663
|
|
|
@@ -144,7 +144,7 @@ def validate_start_time_str(start_time_string):
|
|
|
144
144
|
error_notice('Incorrect Start Time Format', start_time_string+" does no match %Y-%m-%d %H:%M:%S", e)
|
|
145
145
|
return False
|
|
146
146
|
|
|
147
|
-
def open_todo(w=None, i=None, item_type = '
|
|
147
|
+
def open_todo(w=None, i=None, item_type = 'tasks'):
|
|
148
148
|
''' run the launch() function from the todo connector for the provided i(tem) '''
|
|
149
149
|
if not isinstance(i, dict):
|
|
150
150
|
i = db_get_item_by_id(i,item_type)
|
|
@@ -414,7 +414,7 @@ def reindex(t=None):
|
|
|
414
414
|
|
|
415
415
|
def reindex_all():
|
|
416
416
|
|
|
417
|
-
db_query("DROP TABLE taskindex")
|
|
417
|
+
db_query("DROP TABLE taskindex",None,None,0)
|
|
418
418
|
db_query("CREATE VIRTUAL TABLE taskindex USING fts5(id, extended_label, priority, status)")
|
|
419
419
|
db_query("INSERT INTO taskindex(id, extended_label, priority, status) SELECT id, extended_label, priority, status FROM tasks WHERE tasks.status IS NOT '-1' ")
|
|
420
420
|
|
|
@@ -684,7 +684,9 @@ def db_cleanup(widget = None):
|
|
|
684
684
|
# exit()
|
|
685
685
|
|
|
686
686
|
def db_get_item_by_id(id,table = 'tasks'):
|
|
687
|
-
|
|
687
|
+
|
|
688
|
+
if table in ['task','list']:
|
|
689
|
+
table = table+'s'
|
|
688
690
|
if table not in ['tasks','lists']:
|
|
689
691
|
dbg('bad table "'+str(table)+'" passed to db_get_item_by_id',id,l=0)
|
|
690
692
|
return {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nowfocus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: nowfocus: the open source task-tracking self-control panel.
|
|
5
5
|
Author: GitFr33
|
|
6
6
|
Project-URL: Homepage, https://gitlab.com/GitFr33/nowfocus
|
|
@@ -92,40 +92,37 @@ nowfocus is a clean, keyboard-driven project time tracker build with python + GT
|
|
|
92
92
|
- [TimeWarrior](https://timewarrior.net)
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
## Installation
|
|
95
|
+
## Installation
|
|
96
96
|
|
|
97
|
-
Run the following in terminal to install and setup:
|
|
97
|
+
1. Run the following in terminal to install and setup:
|
|
98
98
|
```
|
|
99
99
|
# Install dependencies
|
|
100
|
-
sudo apt install
|
|
100
|
+
sudo apt install pipx gir1.2-appindicator3-0.1 meson libdbus-glib-1-dev patchelf libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev
|
|
101
101
|
|
|
102
102
|
# Set up pipx
|
|
103
103
|
pipx ensurepath
|
|
104
104
|
|
|
105
|
+
# At this point you may need to restart your terminal window
|
|
106
|
+
|
|
105
107
|
# Install nowfocus
|
|
106
108
|
pipx install nowfocus
|
|
107
109
|
|
|
108
110
|
# Enter application directory
|
|
109
|
-
cd ~/.local/pipx/nowfocus
|
|
110
|
-
|
|
111
|
-
# Copy .desktop and icon to .local/share
|
|
112
|
-
cp src/desktop-extras/nowfocus.desktop ~/.local/share/applications/nowfocus.desktop
|
|
113
|
-
cp src/desktop-extras/nowfocus.svg ~/.local/share/icons/nowfocus.png
|
|
114
|
-
cp src/desktop-extras/nowfocus.svg ~/.local/share/icons/hicolor/scalable/apps/nowfocus.svg
|
|
115
|
-
|
|
116
|
-
# Setup autostart
|
|
117
|
-
cp src/desktop-extras/nowfocus.desktop ~/.config/autostart/nowfocus.desktop
|
|
111
|
+
cd ~/.local/share/pipx/venvs/nowfocus/lib/python3.12/site-packages/nowfocus/desktop-extras
|
|
118
112
|
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
src/desktop-extras/set_gsettings_keybinding.sh "Open nowfocus" nowfocus "<Super>space"
|
|
113
|
+
# Copy .desktop and icon to /usr/share
|
|
114
|
+
sudo cp nowfocus.desktop /usr/share/applications/nowfocus.desktop
|
|
115
|
+
sudo cp nowfocus.svg /usr/share/icons/hicolor/scalable/apps/nowfocus.svg
|
|
123
116
|
|
|
124
117
|
# and now Focus!
|
|
125
118
|
nowfocus
|
|
126
119
|
|
|
127
120
|
```
|
|
128
121
|
|
|
122
|
+
2. Set up a keybinding (on Ubuntu or Linux Mint), open **Settings > Keyboard > Keyboard Shortcuts > Custom Shortcuts**, set the **command** to `nowfocus`, and pick whatever key combo you'd like.
|
|
123
|
+
|
|
124
|
+
3. Add the following command to your startup applications: `nowfocus --force`
|
|
125
|
+
|
|
129
126
|
|
|
130
127
|
|
|
131
128
|
## Usage
|
|
@@ -138,7 +135,10 @@ Open nowfocus **Settings** from the indicator menu or tasks window and connect y
|
|
|
138
135
|
|
|
139
136
|
- `F11` Toggle fullscreen
|
|
140
137
|
- `Esc` Close task window
|
|
141
|
-
- `Enter` Start top task (or make a new task with current search phrase if no results)
|
|
138
|
+
- `Enter` Start top/selected task (or make a new task with current search phrase if no results)
|
|
139
|
+
- `Shift Enter` or `Shift Click` Transfer current session time to selected task (or top task if none selected)
|
|
140
|
+
- `Control Enter` or `Control Click` show opetions menu for selected (or top) task
|
|
141
|
+
- `Alt Enter` or `Alt Click` Open todolist for selected (or top) task
|
|
142
142
|
- `Ctrl + P` **Pause** current task
|
|
143
143
|
- `Ctrl + D` Pause current task and mark it **Done**
|
|
144
144
|
- `Ctrl + X` Cancel current task
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
|
-
src/desktop-extras/nowfocus.desktop
|
|
5
|
-
src/desktop-extras/nowfocus.png
|
|
6
|
-
src/desktop-extras/nowfocus.svg
|
|
7
|
-
src/desktop-extras/set_gsettings_keybinding.sh
|
|
8
4
|
src/nowfocus/__init__.py
|
|
9
5
|
src/nowfocus/__main__.py
|
|
10
6
|
src/nowfocus/conf.py
|
|
@@ -34,6 +30,10 @@ src/nowfocus/connectors/todotxt.py
|
|
|
34
30
|
src/nowfocus/connectors/trello.py
|
|
35
31
|
src/nowfocus/connectors/txt.py
|
|
36
32
|
src/nowfocus/connectors/vikunja.py
|
|
33
|
+
src/nowfocus/desktop-extras/nowfocus.desktop
|
|
34
|
+
src/nowfocus/desktop-extras/nowfocus.png
|
|
35
|
+
src/nowfocus/desktop-extras/nowfocus.svg
|
|
36
|
+
src/nowfocus/desktop-extras/set_gsettings_keybinding.sh
|
|
37
37
|
src/nowfocus/icon/cancel.png
|
|
38
38
|
src/nowfocus/icon/cancel.svg
|
|
39
39
|
src/nowfocus/icon/edit.png
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nowfocus
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nowfocus-0.2.5/src → nowfocus-0.2.7/src/nowfocus}/desktop-extras/set_gsettings_keybinding.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|