Branch data Line data Source code
1 : : /* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
2 : : /* cc-timelike-editor.c
3 : : *
4 : : * Copyright 2020 Purism SPC
5 : : *
6 : : * This program is free software: you can redistribute it and/or modify
7 : : * it under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation, either version 2 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * This program is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : * GNU General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : : *
19 : : * Author(s):
20 : : * Mohammed Sadiq <sadiq@sadiqpk.org>
21 : : *
22 : : * SPDX-License-Identifier: GPL-3.0-or-later
23 : : */
24 : :
25 : : #undef G_LOG_DOMAIN
26 : : #define G_LOG_DOMAIN "cc-timelike-editor"
27 : :
28 : : #ifdef HAVE_CONFIG_H
29 : : # include "config.h"
30 : : #endif
31 : :
32 : : #define GNOME_DESKTOP_USE_UNSTABLE_API
33 : : #include <libgnome-desktop/gnome-wall-clock.h>
34 : : #include <gtk/gtk.h>
35 : : #include <glib/gi18n.h>
36 : :
37 : : #include "cc-timelike-entry.h"
38 : : #include "cc-timelike-editor.h"
39 : : #include "cc-timelike-editor-enums.h"
40 : : #include "cc-timelike-editor-layout.h"
41 : :
42 : :
43 : : #define TIMEOUT_INITIAL 500
44 : : #define TIMEOUT_REPEAT 50
45 : :
46 : : #define FILECHOOSER_SCHEMA "org.gtk.Settings.FileChooser"
47 : : #define CLOCK_SCHEMA "org.gnome.desktop.interface"
48 : : #define CLOCK_FORMAT_KEY "clock-format"
49 : : #define SECONDS_PER_MINUTE (60)
50 : : #define SECONDS_PER_HOUR (60 * 60)
51 : : #define SECONDS_PER_DAY (60 * 60 * 24)
52 : :
53 : :
54 : : struct _CcTimelikeEditor
55 : : {
56 : : GtkWidget parent_instance;
57 : :
58 : : GtkButton *am_pm_button;
59 : : GtkStack *am_pm_stack;
60 : : GtkLabel *am_label;
61 : : GtkLabel *pm_label;
62 : : GtkButton *hour_up_button;
63 : : GtkButton *hour_down_button;
64 : : GtkButton *minute_up_button;
65 : : GtkButton *minute_down_button;
66 : : CcTimelikeEntry *timelike_entry;
67 : :
68 : : GtkButton *clicked_button; /* The button currently being clicked */
69 : : GSettings *clock_settings;
70 : : GSettings *filechooser_settings;
71 : :
72 : : guint timer_id;
73 : :
74 : : CcTimelikeEditorMode mode;
75 : : };
76 : :
77 [ # # # # : 0 : G_DEFINE_TYPE (CcTimelikeEditor, cc_timelike_editor, GTK_TYPE_WIDGET)
# # ]
78 : :
79 : : typedef enum {
80 : : PROP_MODE = 1,
81 : : PROP_MINUTE_INCREMENT,
82 : : } CcTimelikeEditorProperty;
83 : :
84 : : static GParamSpec *props[PROP_MINUTE_INCREMENT + 1];
85 : :
86 : : enum {
87 : : TIME_CHANGED,
88 : : N_SIGNALS
89 : : };
90 : :
91 : : static guint signals[N_SIGNALS];
92 : :
93 : : static void
94 : 0 : update_am_pm_widgets (CcTimelikeEditor *self)
95 : : {
96 : : GDesktopClockFormat value;
97 : : gboolean is_am_pm, is_time;
98 : :
99 : 0 : g_assert (CC_IS_TIMELIKE_EDITOR (self));
100 : :
101 : 0 : value = g_settings_get_enum (self->clock_settings, CLOCK_FORMAT_KEY);
102 : 0 : is_am_pm = value == G_DESKTOP_CLOCK_FORMAT_12H;
103 : 0 : is_time = (self->mode == CC_TIMELIKE_EDITOR_MODE_TIME);
104 : :
105 : 0 : cc_timelike_entry_set_am_pm (self->timelike_entry, is_am_pm);
106 : :
107 [ # # # # ]: 0 : gtk_widget_set_visible (GTK_WIDGET (self->am_pm_button), is_am_pm && is_time);
108 : :
109 [ # # # # ]: 0 : if (is_am_pm && is_time)
110 : : {
111 [ # # ]: 0 : if (cc_timelike_entry_get_is_am (self->timelike_entry))
112 : 0 : gtk_stack_set_visible_child (self->am_pm_stack, GTK_WIDGET (self->am_label));
113 : : else
114 : 0 : gtk_stack_set_visible_child (self->am_pm_stack, GTK_WIDGET (self->pm_label));
115 : : }
116 : 0 : }
117 : :
118 : : static void
119 : 0 : timelike_editor_clock_changed_cb (CcTimelikeEditor *self)
120 : : {
121 : 0 : update_am_pm_widgets (self);
122 : 0 : }
123 : :
124 : : static void
125 : 0 : timelike_editor_time_changed_cb (CcTimelikeEditor *self)
126 : : {
127 : 0 : g_assert (CC_IS_TIMELIKE_EDITOR (self));
128 : :
129 : 0 : update_am_pm_widgets (self);
130 : 0 : g_signal_emit (self, signals[TIME_CHANGED], 0);
131 : 0 : }
132 : :
133 : : static void
134 : 0 : editor_change_time_clicked_cb (CcTimelikeEditor *self,
135 : : GtkButton *button)
136 : : {
137 : 0 : g_assert (CC_IS_TIMELIKE_EDITOR (self));
138 : :
139 [ # # ]: 0 : if (button == NULL)
140 : 0 : return;
141 : :
142 [ # # ]: 0 : if (button == self->hour_up_button)
143 : : {
144 : 0 : gtk_editable_set_position (GTK_EDITABLE (self->timelike_entry), 0);
145 : 0 : g_signal_emit_by_name (self->timelike_entry, "change-value", GTK_SCROLL_STEP_UP);
146 : : }
147 [ # # ]: 0 : else if (button == self->hour_down_button)
148 : : {
149 : 0 : gtk_editable_set_position (GTK_EDITABLE (self->timelike_entry), 0);
150 : 0 : g_signal_emit_by_name (self->timelike_entry, "change-value", GTK_SCROLL_STEP_DOWN);
151 : : }
152 [ # # ]: 0 : else if (button == self->minute_up_button)
153 : : {
154 : 0 : gtk_editable_set_position (GTK_EDITABLE (self->timelike_entry), 3);
155 : 0 : g_signal_emit_by_name (self->timelike_entry, "change-value", GTK_SCROLL_STEP_UP);
156 : : }
157 [ # # ]: 0 : else if (button == self->minute_down_button)
158 : : {
159 : 0 : gtk_editable_set_position (GTK_EDITABLE (self->timelike_entry), 3);
160 : 0 : g_signal_emit_by_name (self->timelike_entry, "change-value", GTK_SCROLL_STEP_DOWN);
161 : : }
162 : : }
163 : :
164 : : static gboolean
165 : 0 : editor_change_time_repeat (CcTimelikeEditor *self)
166 : : {
167 [ # # ]: 0 : if (self->clicked_button == NULL)
168 : : {
169 : 0 : self->timer_id = 0;
170 : :
171 : 0 : return G_SOURCE_REMOVE;
172 : : }
173 : :
174 : 0 : editor_change_time_clicked_cb (self, self->clicked_button);
175 : :
176 : 0 : return G_SOURCE_CONTINUE;
177 : : }
178 : :
179 : : static gboolean
180 : 0 : editor_change_time_cb (CcTimelikeEditor *self)
181 : : {
182 : 0 : g_assert (CC_IS_TIMELIKE_EDITOR (self));
183 [ # # ]: 0 : g_clear_handle_id (&self->timer_id, g_source_remove);
184 : :
185 : 0 : editor_change_time_clicked_cb (self, self->clicked_button);
186 : 0 : self->timer_id = g_timeout_add (TIMEOUT_REPEAT,
187 : : (GSourceFunc)editor_change_time_repeat,
188 : : self);
189 : 0 : return G_SOURCE_REMOVE;
190 : : }
191 : :
192 : : static gboolean
193 : 0 : editor_change_time_pressed_cb (CcTimelikeEditor *self,
194 : : gint n_press,
195 : : gdouble x,
196 : : gdouble y,
197 : : GtkGestureClick *click_gesture)
198 : : {
199 : : GtkWidget *button;
200 : :
201 : 0 : g_assert (CC_IS_TIMELIKE_EDITOR (self));
202 : :
203 : 0 : button = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (click_gesture));
204 : :
205 : 0 : self->clicked_button = GTK_BUTTON (button);
206 : : /* Keep changing time until the press is released */
207 : 0 : self->timer_id = g_timeout_add (TIMEOUT_INITIAL,
208 : : (GSourceFunc)editor_change_time_cb,
209 : : self);
210 : 0 : editor_change_time_clicked_cb (self, GTK_BUTTON (button));
211 : 0 : return FALSE;
212 : : }
213 : :
214 : : static gboolean
215 : 0 : editor_change_time_released_cb (CcTimelikeEditor *self)
216 : : {
217 : 0 : self->clicked_button = NULL;
218 [ # # ]: 0 : g_clear_handle_id (&self->timer_id, g_source_remove);
219 : :
220 : 0 : return FALSE;
221 : : }
222 : :
223 : : static void
224 : 0 : editor_am_pm_button_clicked_cb (CcTimelikeEditor *self)
225 : : {
226 : : gboolean is_am;
227 : :
228 : 0 : g_assert (CC_IS_TIMELIKE_EDITOR (self));
229 : 0 : g_assert (cc_timelike_entry_get_am_pm (self->timelike_entry));
230 : :
231 : 0 : is_am = cc_timelike_entry_get_is_am (self->timelike_entry);
232 : : /* Toggle AM PM */
233 : 0 : cc_timelike_entry_set_is_am (self->timelike_entry, !is_am);
234 : 0 : update_am_pm_widgets (self);
235 : 0 : }
236 : :
237 : : static void
238 : 0 : editor_am_pm_stack_changed_cb (CcTimelikeEditor *self)
239 : : {
240 : : GtkWidget *label;
241 : : const gchar *text;
242 : :
243 : 0 : g_assert (CC_IS_TIMELIKE_EDITOR (self));
244 : :
245 : 0 : label = gtk_stack_get_visible_child (self->am_pm_stack);
246 : 0 : text = gtk_label_get_text (GTK_LABEL (label));
247 : 0 : gtk_accessible_update_property (GTK_ACCESSIBLE (self->am_pm_button),
248 : : GTK_ACCESSIBLE_PROPERTY_LABEL, text,
249 : : -1);
250 : 0 : }
251 : :
252 : : static void
253 : 0 : cc_timelike_editor_constructed (GObject *object)
254 : : {
255 : 0 : CcTimelikeEditor *self = (CcTimelikeEditor *)object;
256 : : GDateTime *date;
257 : : char *label;
258 : :
259 : 0 : G_OBJECT_CLASS (cc_timelike_editor_parent_class)->constructed (object);
260 : :
261 : : /* Set localized identifier for AM */
262 : 0 : date = g_date_time_new_utc (1, 1, 1, 0, 0, 0);
263 : 0 : label = g_date_time_format (date, "%p");
264 : 0 : gtk_label_set_label (self->am_label, label);
265 : 0 : g_date_time_unref (date);
266 : 0 : g_free (label);
267 : :
268 : : /* Set localized identifier for PM */
269 : 0 : date = g_date_time_new_utc (1, 1, 1, 12, 0, 0);
270 : 0 : label = g_date_time_format (date, "%p");
271 : 0 : gtk_label_set_label (self->pm_label, label);
272 : 0 : g_date_time_unref (date);
273 : 0 : g_free (label);
274 : 0 : }
275 : :
276 : : static void
277 : 0 : cc_timelike_editor_get_property (GObject *object,
278 : : guint property_id,
279 : : GValue *value,
280 : : GParamSpec *pspec)
281 : : {
282 : 0 : CcTimelikeEditor *self = CC_TIMELIKE_EDITOR (object);
283 : :
284 [ # # # ]: 0 : switch ((CcTimelikeEditorProperty) property_id)
285 : : {
286 : 0 : case PROP_MODE:
287 : 0 : g_value_set_enum (value, cc_timelike_editor_get_mode (self));
288 : 0 : break;
289 : 0 : case PROP_MINUTE_INCREMENT:
290 : 0 : g_value_set_uint (value, cc_timelike_editor_get_minute_increment (self));
291 : 0 : break;
292 : 0 : default:
293 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
294 : 0 : break;
295 : : }
296 : 0 : }
297 : :
298 : : static void
299 : 0 : cc_timelike_editor_set_property (GObject *object,
300 : : guint property_id,
301 : : const GValue *value,
302 : : GParamSpec *pspec)
303 : : {
304 : 0 : CcTimelikeEditor *self = CC_TIMELIKE_EDITOR (object);
305 : :
306 [ # # # ]: 0 : switch ((CcTimelikeEditorProperty) property_id)
307 : : {
308 : 0 : case PROP_MODE:
309 : 0 : cc_timelike_editor_set_mode (self, g_value_get_enum (value));
310 : 0 : break;
311 : 0 : case PROP_MINUTE_INCREMENT:
312 : 0 : cc_timelike_editor_set_minute_increment (self, g_value_get_uint (value));
313 : 0 : break;
314 : 0 : default:
315 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
316 : 0 : break;
317 : : }
318 : 0 : }
319 : :
320 : : static void
321 : 0 : cc_timelike_editor_dispose (GObject *object)
322 : : {
323 : 0 : gtk_widget_dispose_template (GTK_WIDGET (object), CC_TYPE_TIMELIKE_EDITOR);
324 : :
325 : 0 : G_OBJECT_CLASS (cc_timelike_editor_parent_class)->dispose (object);
326 : 0 : }
327 : :
328 : : static void
329 : 0 : cc_timelike_editor_finalize (GObject *object)
330 : : {
331 : 0 : CcTimelikeEditor *self = (CcTimelikeEditor *)object;
332 : :
333 [ # # ]: 0 : g_clear_handle_id (&self->timer_id, g_source_remove);
334 [ # # ]: 0 : g_clear_object (&self->clock_settings);
335 [ # # ]: 0 : g_clear_object (&self->filechooser_settings);
336 : :
337 : 0 : G_OBJECT_CLASS (cc_timelike_editor_parent_class)->finalize (object);
338 : 0 : }
339 : :
340 : : static void
341 : 0 : cc_timelike_editor_class_init (CcTimelikeEditorClass *klass)
342 : : {
343 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
344 : 0 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
345 : :
346 : 0 : object_class->constructed = cc_timelike_editor_constructed;
347 : 0 : object_class->get_property = cc_timelike_editor_get_property;
348 : 0 : object_class->set_property = cc_timelike_editor_set_property;
349 : 0 : object_class->dispose = cc_timelike_editor_dispose;
350 : 0 : object_class->finalize = cc_timelike_editor_finalize;
351 : :
352 : : /**
353 : : * CcTimelikeEditor:mode:
354 : : *
355 : : * What kind of time the editor is meant to represent — a wall clock time,
356 : : * or a duration.
357 : : *
358 : : * This affects whether the AM/PM buttons are potentially shown.
359 : : */
360 : 0 : props[PROP_MODE] =
361 : 0 : g_param_spec_enum ("mode",
362 : : NULL, NULL,
363 : : CC_TYPE_TIMELIKE_EDITOR_MODE,
364 : : CC_TIMELIKE_EDITOR_MODE_TIME,
365 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
366 : :
367 : : /**
368 : : * CcTimelikeEditor:minute-increment:
369 : : *
370 : : * Number of minutes the up/down buttons change the time by, which will
371 : : * always be in the range [1, 59].
372 : : */
373 : 0 : props[PROP_MINUTE_INCREMENT] =
374 : 0 : g_param_spec_uint ("minute-increment",
375 : : NULL, NULL,
376 : : 1, 59, 1,
377 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
378 : :
379 : 0 : g_object_class_install_properties (object_class, G_N_ELEMENTS (props), props);
380 : :
381 : 0 : signals[TIME_CHANGED] =
382 : 0 : g_signal_new ("time-changed",
383 : : G_TYPE_FROM_CLASS (klass),
384 : : G_SIGNAL_RUN_FIRST,
385 : : 0, NULL, NULL,
386 : : NULL,
387 : : G_TYPE_NONE, 0);
388 : :
389 : 0 : gtk_widget_class_set_template_from_resource (widget_class,
390 : : "/org/freedesktop/MalcontentControl/"
391 : : "ui/cc-timelike-editor.ui");
392 : 0 : gtk_widget_class_set_layout_manager_type (widget_class, CC_TYPE_TIMELIKE_EDITOR_LAYOUT);
393 : :
394 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, am_pm_button);
395 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, am_pm_stack);
396 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, am_label);
397 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, pm_label);
398 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, hour_up_button);
399 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, hour_down_button);
400 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, minute_up_button);
401 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, minute_down_button);
402 : 0 : gtk_widget_class_bind_template_child (widget_class, CcTimelikeEditor, timelike_entry);
403 : :
404 : 0 : gtk_widget_class_bind_template_callback (widget_class, editor_change_time_pressed_cb);
405 : 0 : gtk_widget_class_bind_template_callback (widget_class, editor_change_time_released_cb);
406 : 0 : gtk_widget_class_bind_template_callback (widget_class, editor_am_pm_button_clicked_cb);
407 : 0 : gtk_widget_class_bind_template_callback (widget_class, editor_am_pm_stack_changed_cb);
408 : :
409 : 0 : g_type_ensure (CC_TYPE_TIMELIKE_ENTRY);
410 : 0 : }
411 : :
412 : : static void
413 : 0 : cc_timelike_editor_init (CcTimelikeEditor *self)
414 : : {
415 : 0 : gtk_widget_init_template (GTK_WIDGET (self));
416 : :
417 : 0 : self->mode = CC_TIMELIKE_EDITOR_MODE_TIME;
418 : 0 : self->clock_settings = g_settings_new (CLOCK_SCHEMA);
419 : 0 : self->filechooser_settings = g_settings_new (FILECHOOSER_SCHEMA);
420 : :
421 : 0 : g_signal_connect_object (self->clock_settings, "changed::" CLOCK_FORMAT_KEY,
422 : : G_CALLBACK (timelike_editor_clock_changed_cb), self,
423 : : G_CONNECT_SWAPPED);
424 : 0 : g_signal_connect_swapped (self->timelike_entry, "time-changed",
425 : : G_CALLBACK (timelike_editor_time_changed_cb), self);
426 : 0 : update_am_pm_widgets (self);
427 : 0 : }
428 : :
429 : : CcTimelikeEditor *
430 : 0 : cc_timelike_editor_new (void)
431 : : {
432 : 0 : return g_object_new (CC_TYPE_TIMELIKE_EDITOR, NULL);
433 : : }
434 : :
435 : : void
436 : 0 : cc_timelike_editor_set_time (CcTimelikeEditor *self,
437 : : guint hour,
438 : : guint minute)
439 : : {
440 : 0 : g_return_if_fail (CC_IS_TIMELIKE_EDITOR (self));
441 : :
442 : 0 : cc_timelike_entry_set_time (self->timelike_entry, hour, minute);
443 : : }
444 : :
445 : : guint
446 : 0 : cc_timelike_editor_get_hour (CcTimelikeEditor *self)
447 : : {
448 : 0 : g_return_val_if_fail (CC_IS_TIMELIKE_EDITOR (self), 0);
449 : :
450 : 0 : return cc_timelike_entry_get_hour (self->timelike_entry);
451 : : }
452 : :
453 : : guint
454 : 0 : cc_timelike_editor_get_minute (CcTimelikeEditor *self)
455 : : {
456 : 0 : g_return_val_if_fail (CC_IS_TIMELIKE_EDITOR (self), 0);
457 : :
458 : 0 : return cc_timelike_entry_get_minute (self->timelike_entry);
459 : : }
460 : :
461 : : /**
462 : : * cc_timelike_editor_get_mode:
463 : : * @self: a #CcTimelikeEditor
464 : : *
465 : : * Get the value of #CcTimelikeEditor:mode.
466 : : *
467 : : * Returns: the current editor mode
468 : : */
469 : : CcTimelikeEditorMode
470 : 0 : cc_timelike_editor_get_mode (CcTimelikeEditor *self)
471 : : {
472 : 0 : g_return_val_if_fail (CC_IS_TIMELIKE_EDITOR (self), CC_TIMELIKE_EDITOR_MODE_TIME);
473 : :
474 : 0 : return self->mode;
475 : : }
476 : :
477 : : /**
478 : : * cc_timelike_editor_set_mode:
479 : : * @self: a #CcTimelikeEditor
480 : : * @mode: new editor mode
481 : : *
482 : : * Set the value of #CcTimelikeEditor:mode.
483 : : */
484 : : void
485 : 0 : cc_timelike_editor_set_mode (CcTimelikeEditor *self,
486 : : CcTimelikeEditorMode mode)
487 : : {
488 : 0 : g_return_if_fail (CC_IS_TIMELIKE_EDITOR (self));
489 : :
490 [ # # ]: 0 : if (self->mode == mode)
491 : 0 : return;
492 : :
493 : 0 : g_object_freeze_notify (G_OBJECT (self));
494 : :
495 : 0 : self->mode = mode;
496 : 0 : update_am_pm_widgets (self);
497 : 0 : g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODE]);
498 : :
499 : 0 : g_object_thaw_notify (G_OBJECT (self));
500 : : }
501 : :
502 : : /**
503 : : * cc_timelike_editor_get_minute_increment:
504 : : * @self: a #CcTimelikeEditor
505 : : *
506 : : * Get the value of #CcTimelikeEditor:minute-increment.
507 : : *
508 : : * Returns: number of minutes the up/down buttons change the time by, which will
509 : : * always be in the range [1, 59]
510 : : */
511 : : guint
512 : 0 : cc_timelike_editor_get_minute_increment (CcTimelikeEditor *self)
513 : : {
514 : : guint minutes;
515 : :
516 : 0 : g_return_val_if_fail (CC_IS_TIMELIKE_EDITOR (self), 1);
517 : :
518 : 0 : minutes = cc_timelike_entry_get_minute_increment (self->timelike_entry);
519 : :
520 : 0 : g_assert (minutes > 0 && minutes < 60);
521 : :
522 : 0 : return minutes;
523 : : }
524 : :
525 : : /**
526 : : * cc_timelike_editor_set_minute_increment:
527 : : * @self: a #CcTimelikeEditor
528 : : * @minutes: number of minutes the up/down buttons change the time by; must be
529 : : * in the range [1, 59]
530 : : *
531 : : * Set the value of #CcTimelikeEditor:minute-increment.
532 : : */
533 : : void
534 : 0 : cc_timelike_editor_set_minute_increment (CcTimelikeEditor *self,
535 : : guint minutes)
536 : : {
537 : 0 : g_return_if_fail (CC_IS_TIMELIKE_EDITOR (self));
538 : 0 : g_return_if_fail (minutes > 0 && minutes < 60);
539 : :
540 : 0 : cc_timelike_entry_set_minute_increment (self->timelike_entry, minutes);
541 : : }
|