Add postpone button

This commit is contained in:
Gobinath 2017-04-03 14:18:23 -04:00
parent faa015fe7a
commit a8f2ad4a6b
22 changed files with 210 additions and 32 deletions

View File

@ -35,8 +35,9 @@ class BreakScreen:
"""
Read the break_screen.glade and build the user interface.
"""
def __init__(self, on_skip, glade_file, style_sheet_path):
def __init__(self, on_skip, on_postpone, glade_file, style_sheet_path):
self.on_skip = on_skip
self.on_postpone = on_postpone
self.is_pretified = False
self.key_lock_condition = threading.Condition()
self.windows = []
@ -55,6 +56,7 @@ class BreakScreen:
def initialize(self, config, language):
logging.info("Initialize the break screen")
self.skip_button_text = language['ui_controls']['skip']
self.postpone_button_text = language['ui_controls']['postpone']
self.strict_break = config['strict_break']
@ -76,6 +78,15 @@ class BreakScreen:
self.close()
"""
Postpone button press event handler.
"""
def on_postpone_clicked(self, button):
logging.info("User postponed the break")
self.on_postpone()
self.close()
"""
Show/update the count down on all screens.
"""
@ -126,10 +137,13 @@ class BreakScreen:
lbl_message = builder.get_object("lbl_message")
lbl_count = builder.get_object("lbl_count")
btn_skip = builder.get_object("btn_skip")
btn_postpone = builder.get_object("btn_postpone")
lbl_message.set_label(message)
btn_skip.set_label(self.skip_button_text)
btn_skip.set_visible(not self.strict_break)
btn_postpone.set_label(self.postpone_button_text)
btn_postpone.set_visible(not self.strict_break)
self.windows.append(window)
self.count_labels.append(lbl_count)

View File

@ -34,6 +34,7 @@ class SafeEyesCore:
self.long_break_message_index = -1
self.short_break_message_index = -1
self.skipped = False
self.postponed = False
self.active = False
self.running = False
self.show_notification = show_notification
@ -60,6 +61,7 @@ class SafeEyesCore:
self.short_break_duration = config['short_break_duration']
self.break_interval = config['break_interval']
self.idle_time = config['idle_time']
self.postpone_duration = config['postpone_duration']
self.skip_break_window_classes = [x.lower() for x in config['active_window_class']['skip_break']]
self.take_break_window_classes = [x.lower() for x in config['active_window_class']['take_break']]
self.custom_exercises = config['custom_exercises']
@ -169,6 +171,12 @@ class SafeEyesCore:
def skip_break(self):
self.skipped = True
"""
User postponed the break using Postpone button
"""
def postpone_break(self):
self.postponed = True
"""
Scheduler task to execute during every interval
@ -177,14 +185,31 @@ class SafeEyesCore:
if not self.__is_running():
return
next_break_time = datetime.datetime.now() + datetime.timedelta(minutes=self.break_interval)
time_to_wait = self.break_interval # In minutes
if self.postponed:
# Reduce the break count by 1 to show the same break again
if self.break_count == 0:
self.break_count = -1
else:
self.break_count = ((self.break_count - 1) % self.no_of_short_breaks_per_long_break)
if self.__is_long_break():
self.long_break_message_index = (self.long_break_message_index - 1) % len(self.long_break_exercises)
else:
self.short_break_message_index = (self.short_break_message_index - 1) % len(self.short_break_exercises)
# Wait until the postpone time
time_to_wait = self.postpone_duration
self.postponed = False
next_break_time = datetime.datetime.now() + datetime.timedelta(minutes=time_to_wait)
self.update_next_break_info(next_break_time)
# Wait for the pre break warning period
logging.info("Pre-break waiting for {} minutes".format(self.break_interval))
logging.info("Pre-break waiting for {} minutes".format(time_to_wait))
self.notification_condition.acquire()
self.notification_condition.wait(self.break_interval * 60) # In minutes
self.notification_condition.wait(time_to_wait * 60) # Convert to seconds
self.notification_condition.release()
logging.info("Pre-break waiting is over")
@ -264,7 +289,7 @@ class SafeEyesCore:
self.start_break(message)
# Use self.active instead of self.__is_running to avoid idle pause interrupting the break
while seconds and self.active and not self.skipped:
while seconds and self.active and not self.skipped and not self.postponed:
mins, secs = divmod(seconds, 60)
timeformat = '{:02d}:{:02d}'.format(mins, secs)
self.on_countdown(timeformat)
@ -272,16 +297,18 @@ class SafeEyesCore:
seconds -= 1
# Loop terminated because of timeout (not skipped) -> Close the break alert
if not self.skipped:
logging.info("Break wasn't skipped. Automatically terminating the break")
if not self.skipped and not self.postponed:
logging.info("Break is terminated automatically")
self.end_break(audible_alert)
# Reset the skipped flag
self.skipped = False
# Resume
if self.__is_running():
# Schedule the break again
Utility.start_thread(self.__scheduler_job)
self.skipped = False
"""

View File

@ -41,6 +41,7 @@ class SettingsDialog:
self.spin_short_between_long = builder.get_object('spin_short_between_long')
self.spin_time_to_prepare = builder.get_object('spin_time_to_prepare')
self.spin_idle_time_to_pause = builder.get_object('spin_idle_time_to_pause')
self.spin_postpone_duration = builder.get_object('spin_postpone_duration')
self.switch_strict_break = builder.get_object('switch_strict_break')
self.switch_audible_alert = builder.get_object('switch_audible_alert')
self.cmb_language = builder.get_object('cmb_language')
@ -51,6 +52,7 @@ class SettingsDialog:
builder.get_object('lbl_short_per_long').set_label(language['ui_controls']['no_of_short_breaks_between_two_long_breaks'])
builder.get_object('lbl_time_to_prepare').set_label(language['ui_controls']['time_to_prepare_for_break'])
builder.get_object('lbl_idle_time_to_pause').set_label(language['ui_controls']['idle_time'])
builder.get_object('lbl_postpone_duration').set_label(language['ui_controls']['postpone_duration'])
builder.get_object('lbl_strict_break').set_label(language['ui_controls']['strict_break'])
builder.get_object('lbl_audible_alert').set_label(language['ui_controls']['audible_alert'])
builder.get_object('lbl_language').set_label(language['ui_controls']['language'])
@ -63,6 +65,7 @@ class SettingsDialog:
self.spin_short_between_long.set_value(config['no_of_short_breaks_per_long_break'])
self.spin_time_to_prepare.set_value(config['pre_break_warning_time'])
self.spin_idle_time_to_pause.set_value(config['idle_time'])
self.spin_postpone_duration.set_value(config['postpone_duration'])
self.switch_strict_break.set_active(config['strict_break'])
self.switch_audible_alert.set_active(config['audible_alert'])
@ -108,6 +111,7 @@ class SettingsDialog:
self.config['no_of_short_breaks_per_long_break'] = self.spin_short_between_long.get_value_as_int()
self.config['pre_break_warning_time'] = self.spin_time_to_prepare.get_value_as_int()
self.config['idle_time'] = self.spin_idle_time_to_pause.get_value_as_int()
self.config['postpone_duration'] = self.spin_postpone_duration.get_value_as_int()
self.config['strict_break'] = self.switch_strict_break.get_active()
self.config['audible_alert'] = self.switch_audible_alert.get_active()
self.config['language'] = self.languages[self.cmb_language.get_active()]

View File

@ -134,6 +134,13 @@ def on_skipped():
logging.info("User skipped the break")
core.skip_break()
"""
Listen to break screen Postpone action and send the signal to core.
"""
def on_postponed():
logging.info("User postponed the break")
core.postpone_break()
"""
Listen to Settings dialog Save action and write to the config file.
"""
@ -282,7 +289,7 @@ def main():
language = Utility.load_language(config['language'])
tray_icon = TrayIcon(config, language, show_settings, show_about, enable_safeeyes, disable_safeeyes, on_quit)
break_screen = BreakScreen(on_skipped, break_screen_glade, style_sheet_path)
break_screen = BreakScreen(on_skipped, on_postponed, break_screen_glade, style_sheet_path)
break_screen.initialize(config, language)
core = SafeEyesCore(show_notification, show_alert, close_alert, on_countdown, tray_icon.next_break_time)
core.initialize(config, language)

View File

@ -34,6 +34,8 @@
"language": "Jazyk",
"long_break_duration": "Trvání dlouhé přestávky (v sekundách)",
"no_of_short_breaks_between_two_long_breaks": "Počet krátkých přestávek mezi dvěma dlouhými přestávkami",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Ukončit",
"save": "Uložit",
"settings": "Nastavení",

View File

@ -34,6 +34,8 @@
"language": "Sprache",
"long_break_duration": "Lange Pause Intervall (in Sekunden)",
"no_of_short_breaks_between_two_long_breaks": "Anzahl von kleinen Pausen zwischen zwei langen Pausen",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Schließen",
"save": "Speichern",
"settings": "Einstellungen",

View File

@ -34,6 +34,8 @@
"language": "Language",
"long_break_duration": "Long break duration (in seconds)",
"no_of_short_breaks_between_two_long_breaks": "Number of short breaks between two long breaks",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Quit",
"save": "Save",
"settings": "Settings",

View File

@ -34,6 +34,8 @@
"language": "Idioma",
"long_break_duration": "Duración de una pausa larga (en segundos)",
"no_of_short_breaks_between_two_long_breaks": "Número de pausas cortas entre dos pausas largas",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Salir",
"save": "Guardar",
"settings": "Preferencias",

View File

@ -34,6 +34,8 @@
"language": "Langue",
"long_break_duration": "Durée d'une pause longue (en secondes)",
"no_of_short_breaks_between_two_long_breaks": "Nombre de pauses courtes entre deux pauses longues",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Quitter",
"save": "Enregistrer",
"settings": "Paramètres",

View File

@ -34,6 +34,8 @@
"language": "ენა",
"long_break_duration": "დიდი შესვენების ხანგრძლივობა (წამებში)",
"no_of_short_breaks_between_two_long_breaks": "მცირე შესვენებების რაოდენობა ორ დიდ შესვენებას შორის",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "გასვლა",
"save": "დამახსოვრება",
"settings": "პარამეტრები",

View File

@ -34,6 +34,8 @@
"language": "भाषा",
"long_break_duration": "लंबे आराम की अवधि (पलों में)",
"no_of_short_breaks_between_two_long_breaks": "दो बड़े आराम के बीच कितने छोटे आराम",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "बंद",
"save": "रखें",
"settings": "सेटिंग्स",

View File

@ -34,6 +34,8 @@
"language": "Nyelv",
"long_break_duration": "Hosszú szünet hossza (másodpercekben)",
"no_of_short_breaks_between_two_long_breaks": "Hány rövid szünet legyen a hosszabbak között?",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Kilépés",
"save": "Mentés",
"settings": "Beállítások",

View File

@ -34,6 +34,8 @@
"language": "Bahasa",
"long_break_duration": "Durasi istirahat panjang (dalam detik)",
"no_of_short_breaks_between_two_long_breaks": "Jumlah istirahat singkat di antara dua istirahat panjang",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Keluar",
"save": "Simpan",
"settings": "Pengaturan",

View File

@ -34,6 +34,8 @@
"language": "Idioma",
"long_break_duration": "Duração de uma pausa longa (em segundos)",
"no_of_short_breaks_between_two_long_breaks": "Número de pausas curtas entre duas pausas longas",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Sair",
"save": "Salvar",
"settings": "Configuração",

View File

@ -34,6 +34,8 @@
"language": "Язык",
"long_break_duration": "Продолжительность длинного перерыва (в секундах)",
"no_of_short_breaks_between_two_long_breaks": "Количество коротких перерывов между двумя длинными",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Выйти",
"save": "Сохранить",
"settings": "Настройки",

View File

@ -34,6 +34,8 @@
"language": "Jazyk",
"long_break_duration": "Trvanie dlhej prestávky (v sekundách)",
"no_of_short_breaks_between_two_long_breaks": "Počet krátkych prestávok medzi dvomi dlhými prestávkami",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": "Koniec",
"save": "Uložiť",
"settings": "Nastavenia",

View File

@ -34,6 +34,8 @@
"language": "மொழி",
"long_break_duration": "நீண்ட கால இடைவேளை (விநாடிகளில்)",
"no_of_short_breaks_between_two_long_breaks": "இரண்டு நீண்ட இடைவேளைகளுக்கிடையிலான குறுகிய இடைவேளைகள்",
"postpone": "ஒத்தி வை",
"postpone_duration": "இடைவேளையை ஒத்தி வைக்கும் காலம் (நிமிடங்களில்)",
"quit": "நிறுத்து",
"save": "சேமி",
"settings": "அமைப்பு",

View File

@ -34,6 +34,8 @@
"language": "Dil",
"long_break_duration": "Uzun mola süresi (saniye)",
"no_of_short_breaks_between_two_long_breaks": "İki uzun mola arasındaki kısa mola sayısı",
"postpone": "Postpone",
"postpone_duration": "Postpone duration (in minutes)",
"quit": ıkış",
"save": "Kaydet",
"settings": "Ayarlar",

View File

@ -8,6 +8,7 @@
"pre_break_warning_time": 10,
"short_break_duration": 15,
"idle_time": 5,
"postpone_duration": 5,
"strict_break": false,
"audible_alert": false,
"language": "system",

View File

@ -25,7 +25,8 @@
.btn_skip {
color: white;
border-radius: 20px;
font-size: 10pt;
border-radius: 25px;
padding-top: 10px;
padding-bottom: 10px;
padding-left: 25px;
@ -41,13 +42,32 @@
color: black;
}
.btn_postpone{
color: white;
font-size: 10pt;
border-radius: 25px;
padding-top: 10px;
padding-bottom: 10px;
padding-left: 25px;
padding-right: 25px;
border-color: white;
background: transparent;
border-width: 2px;
border-image: none;
}
.btn_postpone:hover {
background: white;
color: black;
}
.lbl_message {
font-size: 16pt;
font-size: 22pt;
color: white;
font-weight: bold;
}
.lbl_count {
font-size: 10pt;
font-size: 12pt;
color: white;
}

View File

@ -25,7 +25,6 @@
<requires lib="gtk+" version="3.10"/>
<object class="GtkWindow" id="window_main">
<property name="can_focus">False</property>
<!-- <property name="type">popup</property> -->
<property name="window_position">center</property>
<property name="hide_titlebar_when_maximized">True</property>
<property name="icon_name">safeeyes</property>
@ -80,21 +79,52 @@
</packing>
</child>
<child>
<object class="GtkButton" id="btn_skip">
<property name="label" translatable="yes">Skip</property>
<object class="GtkBox" id="box_buttons">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<signal name="clicked" handler="on_skip_clicked" swapped="no"/>
<style>
<class name="btn_skip"/>
</style>
<property name="spacing">50</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkButton" id="btn_postpone">
<property name="label" translatable="yes">Postpone</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="valign">center</property>
<signal name="clicked" handler="on_postpone_clicked" swapped="no"/>
<style>
<class name="btn_postpone"/>
</style>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btn_skip">
<property name="label" translatable="yes">Skip</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="valign">center</property>
<signal name="clicked" handler="on_skip_clicked" swapped="no"/>
<style>
<class name="btn_skip"/>
</style>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
@ -109,6 +139,15 @@
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<style>

View File

@ -21,6 +21,12 @@
-->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkAdjustment" id="adjust_idle_time_to_pause">
<property name="lower">1</property>
<property name="upper">60</property>
<property name="step_increment">1</property>
<property name="page_increment">5</property>
</object>
<object class="GtkAdjustment" id="adjust_interval_between_breaks">
<property name="lower">1</property>
<property name="upper">60</property>
@ -52,9 +58,9 @@
<property name="step_increment">1</property>
<property name="page_increment">5</property>
</object>
<object class="GtkAdjustment" id="adjust_idle_time_to_pause">
<object class="GtkAdjustment" id="adjust_postpone_duration">
<property name="lower">1</property>
<property name="upper">60</property>
<property name="upper">15</property>
<property name="step_increment">1</property>
<property name="page_increment">5</property>
</object>
@ -79,7 +85,7 @@
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkGrid" id="layoutt_grid">
<object class="GtkGrid" id="layout_grid">
<property name="visible">True</property>
<property name="app_paintable">True</property>
<property name="can_focus">False</property>
@ -167,6 +173,19 @@
<property name="top_attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_postpone_duration">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="label" translatable="yes">Postpone duration (in minutes)</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_strict_break">
<property name="visible">True</property>
@ -177,7 +196,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -190,7 +209,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">7</property>
<property name="top_attach">8</property>
</packing>
</child>
<child>
@ -203,7 +222,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">8</property>
<property name="top_attach">9</property>
</packing>
</child>
<child>
@ -319,9 +338,18 @@
</packing>
</child>
<child>
<object class="GtkSwitch" id="switch_strict_break">
<object class="GtkSpinButton" id="spin_postpone_duration">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="text" translatable="yes">1</property>
<property name="input_purpose">number</property>
<property name="adjustment">adjust_postpone_duration</property>
<property name="climb_rate">1</property>
<property name="numeric">True</property>
<property name="update_policy">if-valid</property>
<property name="value">5</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -329,7 +357,7 @@
</packing>
</child>
<child>
<object class="GtkSwitch" id="switch_audible_alert">
<object class="GtkSwitch" id="switch_strict_break">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
@ -338,6 +366,16 @@
<property name="top_attach">7</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="switch_audible_alert">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">8</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="cmb_language">
<property name="visible">True</property>
@ -345,7 +383,7 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">8</property>
<property name="top_attach">9</property>
</packing>
</child>
<child>