Skip to content

Commit b19ff98

Browse files
committed
¬
1 parent 0b844f6 commit b19ff98

File tree

4 files changed

+103
-46
lines changed

4 files changed

+103
-46
lines changed

code.leech.pytimer.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id" : "code.leech.pytimer",
33
"runtime" : "org.gnome.Platform",
4-
"runtime-version" : "47",
4+
"runtime-version" : "48",
55
"sdk" : "org.gnome.Sdk",
66
"command" : "pytimer",
77
"finish-args" : [
@@ -32,7 +32,13 @@
3232
"type" : "git",
3333
"url" : "file:///home/carbon751/Projects"
3434
}
35+
],
36+
"config-opts" : [
37+
"--libdir=lib"
3538
]
3639
}
37-
]
40+
],
41+
"build-options" : {
42+
"env" : { }
43+
}
3844
}

code.leech.pytimer.json~

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"id" : "code.leech.pytimer",
3+
"runtime" : "org.gnome.Platform",
4+
"runtime-version" : "47",
5+
"sdk" : "org.gnome.Sdk",
6+
"command" : "pytimer",
7+
"finish-args" : [
8+
"--share=network",
9+
"--share=ipc",
10+
"--socket=fallback-x11",
11+
"--device=dri",
12+
"--socket=wayland"
13+
],
14+
"cleanup" : [
15+
"/include",
16+
"/lib/pkgconfig",
17+
"/man",
18+
"/share/doc",
19+
"/share/gtk-doc",
20+
"/share/man",
21+
"/share/pkgconfig",
22+
"*.la",
23+
"*.a"
24+
],
25+
"modules" : [
26+
{
27+
"name" : "pytimer",
28+
"builddir" : true,
29+
"buildsystem" : "meson",
30+
"sources" : [
31+
{
32+
"type" : "git",
33+
"url" : "file:///home/carbon751/Projects"
34+
}
35+
]
36+
}
37+
]
38+
}

src/window.py

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import math
2+
import time
23
import gi
34
gi.require_version('Gtk', '4.0')
45
gi.require_version('Adw', '1')
@@ -23,38 +24,42 @@ def __init__(self, **kwargs):
2324
self.timer_running = False
2425
self.remaining_seconds = 0
2526
self.total_seconds = 0
27+
self.elapsed_time = 0
28+
self.start_time = 0
2629
self.timeout_id = None
2730

28-
# Create start button
29-
self.start_button = Gtk.Button(
30-
icon_name="media-playback-start-symbolic",
31-
css_classes=["circular"]
32-
)
33-
self.start_button.set_valign(Gtk.Align.END)
31+
# Create buttons programmatically
32+
self.start_button = Gtk.Button()
33+
self.start_button.set_icon_name("media-playback-start-symbolic")
34+
self.start_button.add_css_class("circular")
35+
self.start_button.add_css_class("raised")
3436
self.start_button.connect('clicked', self._on_start_clicked)
35-
self.button_box.append(self.start_button)
3637

37-
# Create reset button
38-
self.reset_button = Gtk.Button(
39-
icon_name="view-refresh-symbolic",
40-
css_classes=["circular", "destructive-action"]
41-
)
42-
self.reset_button.set_valign(Gtk.Align.END)
38+
self.reset_button = Gtk.Button()
39+
self.reset_button.set_icon_name("edit-undo-symbolic")
40+
self.reset_button.add_css_class("circular")
41+
self.reset_button.add_css_class("small")
42+
self.reset_button.add_css_class("destructive-action")
43+
self.reset_button.set_visible(False)
4344
self.reset_button.connect('clicked', self._on_reset_clicked)
44-
self.reset_button.set_visible(False) # Initially hidden
45-
self.button_box.append(self.reset_button)
4645

47-
# Set up drawing area
48-
self.progress_circle.set_draw_func(self.draw_timer_arc, None)
46+
# Add buttons to GtkFixed and set positions
47+
self.button_box.put(self.start_button, 15, 0)
48+
self.button_box.put(self.reset_button, 65, 0)
4949

5050
# Connect signals
5151
self.minutes_spin.connect('value-changed', self._on_minutes_changed)
5252

53+
# Set up drawing area
54+
self.progress_circle.set_draw_func(self.draw_timer_arc, None)
55+
5356
# Add CSS for styling
5457
css_provider = Gtk.CssProvider()
5558
css_provider.load_from_data(b"""
5659
.timer-label { font-size: 48px; font-weight: 300; }
60+
.button-box { min-width: 300px; }
5761
button.circular { padding: 4px; margin: 2px; border-radius: 9999px; }
62+
button.small { padding: 2px; }
5863
headerbar { padding: 0; min-height: 24px; box-shadow: none; border-bottom: none; }
5964
window { margin: 0; }
6065
""")
@@ -71,9 +76,12 @@ def __init__(self, **kwargs):
7176
def _on_reset_clicked(self, button):
7277
self.remaining_seconds = 0
7378
self.total_seconds = 0
79+
self.elapsed_time = 0
7480
self._update_time_label()
7581
self.reset_button.set_visible(False)
82+
self.minutes_spin.set_sensitive(True)
7683
self.progress_circle.queue_draw()
84+
self._update_start_button_state()
7785

7886
def _on_start_clicked(self, button):
7987
if not self.timer_running:
@@ -82,25 +90,31 @@ def _on_start_clicked(self, button):
8290
if minutes > 0:
8391
self.total_seconds = minutes * 60
8492
self.remaining_seconds = self.total_seconds
93+
if self.remaining_seconds == 0:
94+
self._on_reset_clicked(None) # Reset the timer if it has finished naturally
95+
minutes = self.minutes_spin.get_value_as_int()
96+
if minutes > 0:
97+
self.total_seconds = minutes * 60
98+
self.remaining_seconds = self.total_seconds
99+
self.start_time = time.time() - self.elapsed_time
85100
self._start_timer()
86101
button.set_icon_name("media-playback-stop-symbolic")
87102
else:
88103
self._stop_timer()
89104
button.set_icon_name("media-playback-start-symbolic")
90-
if self.remaining_seconds > 0:
91-
self.reset_button.set_visible(True)
105+
self.reset_button.set_visible(True)
92106

93107
def draw_timer_arc(self, area, cr, width, height, data):
94108
center_x = width / 2
95109
center_y = height / 2
96110
radius = min(width, height) / 2 - 10
97-
cr.set_source_rgba(0.9, 0.9, 0.9, 0.2)
111+
cr.set_source_rgba(0.7686, 0.7686, 0.7686, 0.5) # Converted from #c4c4c4
98112
cr.set_line_width(8)
99113
cr.arc(center_x, center_y, radius, 0, 2 * math.pi)
100114
cr.stroke()
101115
if self.total_seconds > 0:
102116
cr.set_source_rgb(0.2, 0.6, 1.0)
103-
progress = 1 - (self.remaining_seconds / self.total_seconds)
117+
progress = self.elapsed_time / self.total_seconds
104118
cr.arc(center_x, center_y, radius, -math.pi/2,
105119
2 * math.pi * progress - math.pi/2)
106120
cr.stroke()
@@ -119,38 +133,47 @@ def _update_start_button_state(self):
119133

120134
def _start_timer(self):
121135
self.timer_running = True
122-
self.timeout_id = GLib.timeout_add_seconds(1, self._update_timer)
136+
self.timeout_id = GLib.timeout_add(16, self._update_timer) # Update every ~16ms for 60fps
123137
self.minutes_spin.set_sensitive(False)
138+
self.reset_button.set_visible(False)
124139

125140
def _stop_timer(self):
126141
self.timer_running = False
127142
if self.timeout_id:
128143
GLib.source_remove(self.timeout_id)
129144
self.timeout_id = None
130-
self.minutes_spin.set_sensitive(True)
145+
self.elapsed_time = time.time() - self.start_time # Save the elapsed time
146+
self.minutes_spin.set_sensitive(False) # Disable minutes_spin when paused
131147
self._update_start_button_state()
132148

133149
def _update_timer(self):
134150
if self.remaining_seconds > 0:
135-
self.remaining_seconds -= 1
151+
self.elapsed_time = time.time() - self.start_time
152+
self.remaining_seconds = self.total_seconds - self.elapsed_time
136153
self._update_time_label()
137154
self.progress_circle.queue_draw()
138-
return True
155+
if self.remaining_seconds > 0:
156+
return True
157+
else:
158+
self._timer_finished()
159+
return False
139160
else:
140161
self._timer_finished()
141162
return False
142163

143164
def _update_time_label(self):
144-
minutes = self.remaining_seconds // 60
145-
seconds = self.remaining_seconds % 60
165+
if self.remaining_seconds < 0:
166+
self.remaining_seconds = 0
167+
minutes = int(self.remaining_seconds // 60)
168+
seconds = int(self.remaining_seconds % 60)
146169
self.time_label.set_label(f"{minutes:02d}:{seconds:02d}")
147170

148171
def _timer_finished(self):
149172
self.timer_running = False
150173
self.start_button.set_icon_name("media-playback-start-symbolic")
151174
self.minutes_spin.set_sensitive(True)
152-
self.remaining_seconds = 0
153-
self.total_seconds = 0
154-
self._update_time_label()
155-
self.progress_circle.queue_draw()
156175
self._update_start_button_state()
176+
self.elapsed_time = 0 # Reset elapsed time when the timer finishes
177+
178+
def on_close_button_clicked(self, button):
179+
self.close()

src/window.ui

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,14 @@
8585
<object class="AdwHeaderBar" id="header_bar">
8686
<property name="hexpand">true</property>
8787
<property name="title-widget">
88-
<object class="GtkBox">
89-
<property name="orientation">horizontal</property>
90-
<property name="halign">center</property>
91-
<property name="valign">end</property>
92-
<property name="margin-bottom">2</property>
93-
<child>
94-
<object class="GtkBox" id="button_box">
95-
<property name="orientation">horizontal</property>
96-
<property name="spacing">6</property>
97-
</object>
98-
</child>
88+
<object class="GtkFixed" id="button_box">
9989
</object>
10090
</property>
10191
<child type="start">
10292
<object class="GtkMenuButton">
10393
<property name="valign">center</property>
104-
<property name="margin-start">6</property>
105-
<property name="margin-bottom">2</property>
94+
<property name="margin-start">12</property>
95+
<property name="margin-bottom">4</property>
10696
<property name="icon-name">open-menu-symbolic</property>
10797
<property name="menu-model">primary_menu</property>
10898
<style>

0 commit comments

Comments
 (0)