diff options
author | Stefano Karapetsas <[email protected]> | 2014-01-30 16:04:57 +0100 |
---|---|---|
committer | Stefano Karapetsas <[email protected]> | 2014-01-30 16:04:57 +0100 |
commit | 8795f06d464700494234e589020e5e29854aeb8c (patch) | |
tree | f2525b646023e533f03d5c80240563b89ab5b152 /timer-applet/src | |
parent | c8a85a6aa040c1d2505b957af4cfb4bd39466504 (diff) | |
parent | 064212a25bea1fcf8901cd0a1d55aae0899f627c (diff) | |
download | mate-applets-8795f06d464700494234e589020e5e29854aeb8c.tar.bz2 mate-applets-8795f06d464700494234e589020e5e29854aeb8c.tar.xz |
Merge branch 'dev-timer-applet'
Closes #45
https://github.com/mate-desktop/mate-applets/issues/45
Diffstat (limited to 'timer-applet/src')
33 files changed, 0 insertions, 2957 deletions
diff --git a/timer-applet/src/Makefile.am b/timer-applet/src/Makefile.am deleted file mode 100644 index d266f640..00000000 --- a/timer-applet/src/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -SUBDIRS = timerapplet - -libexec_SCRIPTS = timer-applet - -EXTRA_DIST = \ - timer-applet diff --git a/timer-applet/src/timer-applet b/timer-applet/src/timer-applet deleted file mode 100755 index cd550fbb..00000000 --- a/timer-applet/src/timer-applet +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2010 Kenny Meyer <[email protected]> -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from os import path -import gettext -import locale -import sys -import gtk -import mateapplet -from timerapplet import config -from timerapplet.controllers import GlobalController, TimerApplet, TimerService, TimerManagerService -from timerapplet.core import AppletMateConfWrapper, Timer - -from dbus.mainloop.glib import DBusGMainLoop -DBusGMainLoop(set_as_default=True) - -DBUS_BUS_NAME = 'net.launchpad.timerapplet.TimerApplet' -DBUS_OBJ_NAMESPACE = '/net/launchpad/timerapplet/TimerApplet' - -gettext.bindtextdomain(config.GETTEXT_PACKAGE, config.LOCALE_DIR) -gettext.bind_textdomain_codeset(config.GETTEXT_PACKAGE, 'UTF-8') -gettext.textdomain(config.GETTEXT_PACKAGE) -locale.bindtextdomain(config.GETTEXT_PACKAGE, config.LOCALE_DIR) -locale.bind_textdomain_codeset(config.GETTEXT_PACKAGE, 'UTF-8') -locale.textdomain(config.GETTEXT_PACKAGE) - -global_controller = GlobalController() -timer_manager_obj_path = path.join(DBUS_OBJ_NAMESPACE, 'TimerManager') -print 'Timer Manager D-Bus object path: %s' % timer_manager_obj_path - -timer_manager = None -try: - timer_manager = TimerManagerService(DBUS_BUS_NAME, timer_manager_obj_path) -except Exception, err: - print 'ERROR: Could not start TimerManagerService. D-Bus support will not be available. Error message: %s' % err - -def check_dependencies(): - # Check for optional dependencies - try: - import dbus # >= 0.80 - except ImportError, err: - print 'Missing optional dependency: %s' % err - - # Check for required dependencies - try: - import gobject # >= 2.12 - import gtk # >= 2.10, includes pango - import gtk.glade # >= 2.10 - import mateconf # >= 2.18 - import mate # >= 2.18, includes matecomponent.ui - import mateapplet # >= 2.18, included in python-mate2-desktop - import pynotify # >= 0.1.1 - except ImportError, err: - dialog = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, - buttons=gtk.BUTTONS_CLOSE, - message_format='%s\n\nPlease install required dependencies.' % err) - dialog.run() - dialog.destroy() - sys.exit(1) - -def get_timer_id(mateconf_wrapper): - path_components = mateconf_wrapper.get_base_path().split('/') - - # Use the second component from the end, which should usually be 'applet_*', - # where '*' is some integer assigned by the system. - # It could also be 'timer-applet' if we're running in standalone mode. - # D-Bus doesn't like hyphens in object paths, so we have to replace them - # with underscores. - return path_components[-2].replace('-', '_') - -def applet_factory(applet, iid): - check_dependencies() - - timer = Timer() - mateconf_wrapper = AppletMateConfWrapper(applet, - '/schemas/apps/timer-applet/prefs', - '/apps/timer-applet/prefs') - timer_id = get_timer_id(mateconf_wrapper) - print 'Timer ID: %s' % timer_id - - if timer_manager is not None: - timer_manager.register_timer_id(timer_id) - applet.connect('destroy', lambda sender: timer_manager.unregister_timer_id(timer_id)) - - TimerApplet(global_controller.get_presets_store(), - global_controller.get_manage_presets_dialog(), - applet, - timer, - mateconf_wrapper) - - timer_obj_path = path.join(DBUS_OBJ_NAMESPACE, 'Timers', timer_id) - print 'Timer D-Bus object path: %s' % timer_obj_path - - try: - TimerService(DBUS_BUS_NAME, timer_obj_path, timer) - except Exception, err: - print 'ERROR: Could not start TimerService. D-Bus support will not be available. Error message: %s' % err - - return True - -if __name__ == '__main__': - windowed_mode = (len(sys.argv) > 1 and sys.argv[1] == '-w') - - if windowed_mode: - win = gtk.Window() - win.set_title('Timer Applet') - applet = mateapplet.Applet() - applet_factory(applet, None) - applet.reparent(win) - - applet.connect('destroy', gtk.main_quit) - win.show() - - gtk.main() - else: - mateapplet.matecomponent_factory( - 'OAFIID:TimerApplet_Factory', - mateapplet.Applet.__gtype__, - config.PACKAGE, - config.VERSION, - applet_factory) diff --git a/timer-applet/src/timerapplet/Makefile.am b/timer-applet/src/timerapplet/Makefile.am deleted file mode 100644 index 08f474c0..00000000 --- a/timer-applet/src/timerapplet/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -SUBDIRS = controllers core ui - -defs.py: defs.py.in Makefile - sed -e "s|\@PACKAGE\@|$(PACKAGE)|" \ - -e "s|\@VERSION\@|$(VERSION)|" \ - -e "s|\@RESOURCESDIR\@|$(pkgdatadir)|" \ - -e "s|\@IMAGESDIR\@|$(datadir)/pixmaps|" \ - -e "s|\@LOCALEDIR\@|$(localedir)|" \ - -e "s|\@GETTEXT_PACKAGE\@|$(GETTEXT_PACKAGE)|" $< > $@ - -EXTRA_DIST = \ - defs.py.in - -CLEANFILES = \ - defs.py - -# Need this so that defs.py is actually created after cleaning. -BUILT_SOURCES = defs.py - -moduledir = $(pythondir)/timerapplet -module_PYTHON = \ - __init__.py \ - config.py \ - defs.py \ - utils.py \ - logger.py - diff --git a/timer-applet/src/timerapplet/__init__.py b/timer-applet/src/timerapplet/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/timer-applet/src/timerapplet/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/timer-applet/src/timerapplet/config.py b/timer-applet/src/timerapplet/config.py deleted file mode 100644 index 42376845..00000000 --- a/timer-applet/src/timerapplet/config.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import os.path as path - -try: - from defs import * -except ImportError: - PACKAGE = 'timer-applet' - VERSION = '0' - GETTEXT_PACKAGE = '' - LOCALE_DIR = '' - RESOURCES_DIR = path.join(path.dirname(__file__), '../../data') - IMAGES_DIR = path.join(path.dirname(__file__), '../../images') - -print 'Using these definitions:' -print 'GETTEXT_PACKAGE: %s' % GETTEXT_PACKAGE -print 'LOCALE_DIR: %s' % LOCALE_DIR -print 'RESOURCES_DIR: %s' % RESOURCES_DIR -print 'IMAGES_DIR: %s' % IMAGES_DIR - -GLADE_PATH = path.join(RESOURCES_DIR, 'timer-applet.glade') -POPUP_MENU_FILE_PATH = path.join(RESOURCES_DIR, 'TimerApplet.xml') -ICON_PATH = path.join(IMAGES_DIR, 'timer-applet.png') -PRESETS_PATH = path.expanduser('~/.config/mate/timer-applet/presets.xml') -DEFAULT_SOUND_PATH = '/usr/share/sounds/gtk-events/clicked.wav' diff --git a/timer-applet/src/timerapplet/controllers/GlobalController.py b/timer-applet/src/timerapplet/controllers/GlobalController.py deleted file mode 100644 index fd3af2b1..00000000 --- a/timer-applet/src/timerapplet/controllers/GlobalController.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from gettext import gettext as _ -import gtk -from timerapplet import core -from timerapplet import ui -from timerapplet import utils -from timerapplet import config - -class GlobalController(object): - def __init__(self): - self._presets_store = core.PresetsStore(config.PRESETS_PATH) - self._manage_presets_dialog = ui.ManagePresetsDialog(config.GLADE_PATH, - self._presets_store.get_model(), - lambda row_iter: utils.get_preset_display_text(self._presets_store, - row_iter)) - - self._manage_presets_dialog.connect('clicked-add', self._on_mgr_clicked_add) - self._manage_presets_dialog.connect('clicked-edit', self._on_mgr_clicked_edit) - self._manage_presets_dialog.connect('clicked-remove', self._on_mgr_clicked_remove) - - gtk.window_set_default_icon_from_file(config.ICON_PATH) - - def get_presets_store(self): - return self._presets_store - - def get_manage_presets_dialog(self): - return self._manage_presets_dialog - - def _on_mgr_clicked_add(self, sender, data=None): - add_dialog = ui.AddEditPresetDialog( - config.GLADE_PATH, - _('Add Preset'), - lambda name: utils.is_valid_preset_name(name, self._presets_store)) - - result = add_dialog.get_preset() - if result is not None: - (name, hours, minutes, seconds, command, next_timer, auto_start) = result - self._presets_store.add_preset(name, hours, minutes, seconds, - command, next_timer, auto_start) - - def _on_mgr_clicked_edit(self, sender, row_path, data=None): - row_iter = self._presets_store.get_model().get_iter(row_path) - (name, hours, minutes, seconds, command, next_timer, auto_start) = \ - self._presets_store.get_preset(row_iter) - - edit_dialog = ui.AddEditPresetDialog(config.GLADE_PATH, - _('Edit Preset'), - lambda name: utils.is_valid_preset_name(name, - self._presets_store, - (name,)), - name, - hours, - minutes, - seconds, - command, - next_timer, - auto_start - ) - - result = edit_dialog.get_preset() - if result is not None: - (name, hours, minutes, seconds, command, next_timer, auto_start) = result - self._presets_store.modify_preset(row_iter, name, hours, minutes, - seconds, command, next_timer, - auto_start) - - def _on_mgr_clicked_remove(self, sender, row_path, data=None): - row_iter = self._presets_store.get_model().get_iter(row_path) - self._presets_store.remove_preset(row_iter) - - # TODO - def _on_mgr_next_timer_is_being_edited(self, sender, row_path, data=None): - """Show a dropdown widget to help completing the next timer.""" - raise NotImplementedError("Not implemented, yet") - - diff --git a/timer-applet/src/timerapplet/controllers/Makefile.am b/timer-applet/src/timerapplet/controllers/Makefile.am deleted file mode 100644 index bb5018d6..00000000 --- a/timer-applet/src/timerapplet/controllers/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -moduledir = $(pythondir)/timerapplet/controllers -module_PYTHON = \ - __init__.py \ - GlobalController.py \ - TimerApplet.py \ - TimerManagerService.py \ - TimerService.py - diff --git a/timer-applet/src/timerapplet/controllers/TimerApplet.py b/timer-applet/src/timerapplet/controllers/TimerApplet.py deleted file mode 100644 index 2771038c..00000000 --- a/timer-applet/src/timerapplet/controllers/TimerApplet.py +++ /dev/null @@ -1,637 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# Copyright (C) 2010 Kenny Meyer <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from gettext import gettext as _ -from gettext import ngettext -from datetime import datetime, timedelta -import mateapplet -import gst -import gtk -import gtk.glade as glade -import gtk.gdk as gdk -import subprocess -import shlex -import threading -from timerapplet import config -from timerapplet import core -from timerapplet import ui -from timerapplet import utils - -def on_widget_button_press_event(sender, event, data=None): - if event.button != 1: - sender.emit_stop_by_name('button-press-event') - return False - -def force_no_focus_padding(widget): - gtk.rc_parse_string('\n' - ' style "timer-applet-button-style"\n' - ' {\n' - ' GtkWidget::focus-line-width=0\n' - ' GtkWidget::focus-padding=0\n' - ' }\n' - '\n' - ' widget "*.timer-applet-button" style "timer-applet-button-style"\n' - '\n') - widget.set_name('timer-applet-button') - -class TimerApplet(object): - # MateConf key identifiers - ## You can find Timer Applet's schemas file in data/timer-applet.schemas.in - _SHOW_REMAINING_TIME_KEY = 'show_remaining_time' - _PLAY_SOUND_KEY = 'play_notification_sound' - _USE_CUSTOM_SOUND_KEY = 'use_custom_notification_sound' - _SHOW_POPUP_NOTIFICATION_KEY = 'show_popup_notification' - _SHOW_PULSING_ICON_KEY = 'show_pulsing_icon' - _CUSTOM_SOUND_PATH_KEY = 'custom_notification_sound_path' - - _PRESETS_PLACEHOLDER_NAME = 'Placeholder' - _PRESETS_PLACEHOLDER_PATH = '/popups/popup/Presets/' + _PRESETS_PLACEHOLDER_NAME - _PRESETS_PATH = '/popups/popup/Presets' - - def __init__(self, presets_store, manage_presets_dialog, applet, timer, mateconf_wrapper): - self._presets_store = presets_store - self._manage_presets_dialog = manage_presets_dialog - self._applet = applet - self._timer = timer - - self._gst_playbin = gst.element_factory_make('playbin', 'player') - def bus_event(bus, message): - t = message.type - if t == gst.MESSAGE_EOS: - self._gst_playbin.set_state(gst.STATE_NULL) - elif t == gst.MESSAGE_ERROR: - self._gst_playbin.set_state(gst.STATE_NULL) - err, debug = message.parse_error() - print 'Error playing sound: %s' % err, debug - return True - self._gst_playbin.get_bus().add_watch(bus_event) - - self._status_button = ui.StatusButton() - self._notifier = ui.Notifier('TimerApplet', gtk.STOCK_DIALOG_INFO, self._status_button) - self._start_next_timer_dialog = ui.StartNextTimerDialog( - config.GLADE_PATH, - "Start next timer", - "Would you like to start the next timer?") - self._start_timer_dialog = ui.StartTimerDialog(config.GLADE_PATH, - lambda name: utils.is_valid_preset_name(name, - self._presets_store), - self._presets_store.get_model(), - lambda row_iter: utils.get_preset_display_text(self._presets_store, - row_iter)) - self._continue_dialog = ui.ContinueTimerDialog(config.GLADE_PATH, - _('Continue timer countdown?'), - _('The timer is currently paused. Would you like to continue countdown?')) - self._preferences_dialog = ui.PreferencesDialog(config.GLADE_PATH) - self._mateconf = mateconf_wrapper - - self._about_dialog = glade.XML(config.GLADE_PATH, 'about_dialog').get_widget('about_dialog') - self._about_dialog.set_version(config.VERSION) - - self._applet.set_applet_flags(mateapplet.EXPAND_MINOR) - self._applet.setup_menu_from_file( - None, - config.POPUP_MENU_FILE_PATH, - None, - [('PauseTimer', lambda component, verb: self._timer.stop()), - ('ContinueTimer', lambda component, verb: self._timer.start()), - ('StopTimer', lambda component, verb: self._timer.reset()), - ('RestartTimer', lambda component, verb: self._restart_timer()), - ('StartNextTimer', lambda component, verb: self._start_next_timer()), - ('ManagePresets', lambda component, verb: self._manage_presets_dialog.show()), - ('Preferences', lambda component, - verb: self._preferences_dialog.show()), - ('About', lambda component, verb: self._about_dialog.show())] - ) - self._applet.add(self._status_button) - - # Remove padding around button contents. - force_no_focus_padding(self._status_button) - - # TODO: - # Fix bug in which button would not propogate middle-clicks - # and right-clicks to the applet. - self._status_button.connect('button-press-event', on_widget_button_press_event) - - self._status_button.set_relief(gtk.RELIEF_NONE) - self._status_button.set_icon(config.ICON_PATH); - - self._applet.set_tooltip_text(_("Timer Applet")) - - self._connect_signals() - self._update_status_button() - self._update_popup_menu() - self._update_preferences_dialog() - self._status_button.show() - self._applet.show() - - def _connect_signals(self): - self._applet.connect('change-orient', lambda applet, orientation: self._update_status_button()) - self._applet.connect('change-size', lambda applet, size: self._update_status_button()) - self._applet.connect('change-background', self._on_applet_change_background) - self._applet.connect('destroy', self._on_applet_destroy) - - self._presets_store.get_model().connect('row-deleted', - lambda model, - row_path: self._update_popup_menu()) - self._presets_store.get_model().connect('row-changed', - lambda model, - row_path, - row_iter: self._update_popup_menu()) - - self._timer.connect('time-changed', self._on_timer_time_changed) - self._timer.connect('state-changed', self._on_timer_state_changed) - self._status_button.connect('clicked', self._on_status_button_clicked) - self._start_timer_dialog.connect('clicked-start', - self._on_start_dialog_clicked_start) - self._start_timer_dialog.connect('clicked-manage-presets', - self._on_start_dialog_clicked_manage_presets) - self._start_timer_dialog.connect('clicked-save', - self._on_start_dialog_clicked_save) - self._start_timer_dialog.connect('clicked-preset', - self._on_start_dialog_clicked_preset) - self._start_timer_dialog.connect('double-clicked-preset', - self._on_start_dialog_double_clicked_preset) - - self._preferences_dialog.connect('show-remaining-time-changed', self._on_prefs_show_time_changed) - self._preferences_dialog.connect('play-sound-changed', self._on_prefs_play_sound_changed) - self._preferences_dialog.connect('use-custom-sound-changed', self._on_prefs_use_custom_sound_changed) - self._preferences_dialog.connect('show-popup-notification-changed', self._on_prefs_show_popup_notification_changed) - self._preferences_dialog.connect('show-pulsing-icon-changed', self._on_prefs_show_pulsing_icon_changed) - self._preferences_dialog.connect('custom-sound-path-changed', self._on_prefs_custom_sound_path_changed) - - self._about_dialog.connect('delete-event', gtk.Widget.hide_on_delete) - self._about_dialog.connect('response', lambda dialog, response_id: self._about_dialog.hide()) - - self._mateconf.add_notification(TimerApplet._SHOW_REMAINING_TIME_KEY, self._on_mateconf_changed) - self._mateconf.add_notification(TimerApplet._PLAY_SOUND_KEY, self._on_mateconf_changed) - self._mateconf.add_notification(TimerApplet._USE_CUSTOM_SOUND_KEY, self._on_mateconf_changed) - self._mateconf.add_notification(TimerApplet._SHOW_PULSING_ICON_KEY, self._on_mateconf_changed) - self._mateconf.add_notification(TimerApplet._SHOW_POPUP_NOTIFICATION_KEY, self._on_mateconf_changed) - self._mateconf.add_notification(TimerApplet._CUSTOM_SOUND_PATH_KEY, self._on_mateconf_changed) - - ## Private methods for updating UI ## - - def _update_status_button(self): - current_state = self._timer.get_state() - if current_state == core.Timer.STATE_IDLE: - print 'Idle' - # This label text should not be visible because the label - # is hidden when the timer is idle. - self._status_button.set_label('--:--:--') - self._status_button.set_tooltip(_('Click to start a new timer countdown.')) - elif current_state == core.Timer.STATE_RUNNING: - print 'Running' - elif current_state == core.Timer.STATE_PAUSED: - print 'Paused' - self._status_button.set_tooltip(_('Paused. Click to continue timer countdown.')) - elif current_state == core.Timer.STATE_FINISHED: - print 'Finished' - self._status_button.set_label(_('Finished')) - name_str = self._timer.get_name() - time_str = utils.get_display_text_from_datetime(self._timer.get_end_time()) - if len(name_str) > 0: - # "<timer name>" finished at <time> - self._status_button.set_tooltip(_('"%s" finished at %s.\nClick to stop timer.') % (name_str, time_str)) - else: - # Timer finished at <time> - self._status_button.set_tooltip(_('Timer finished at %s.\nClick to stop timer.') % time_str) - - self._status_button.set_sensitized(current_state == core.Timer.STATE_RUNNING or - current_state == core.Timer.STATE_FINISHED) - self._status_button.set_use_icon(current_state == core.Timer.STATE_IDLE) - self._status_button.set_show_remaining_time(current_state != core.Timer.STATE_IDLE and - self._mateconf.get_bool(TimerApplet._SHOW_REMAINING_TIME_KEY)) - - if current_state == core.Timer.STATE_PAUSED: - self._status_button.set_pie_fill_color(0.4, 0.4, 0.4) - else: - # Use theme color - color = self._applet.style.base[gtk.STATE_SELECTED] - red = color.red / 65535.0 - green = color.green / 65535.0 - blue = color.blue / 65535.0 - self._status_button.set_pie_fill_color(red, green, blue) - - orientation = self._applet.get_orient() - size = self._applet.get_size() - use_vertical = (orientation == mateapplet.ORIENT_LEFT or - orientation == mateapplet.ORIENT_RIGHT or - size >= mateapplet.SIZE_MEDIUM) - self._status_button.set_use_vertical_layout(use_vertical) - - def _update_popup_menu(self): - popup = self._applet.get_popup_component() - - timer_state = self._timer.get_state() - has_next_timer = self._timer.get_next_timer() - show_pause = (timer_state == core.Timer.STATE_RUNNING) - show_continue = (timer_state == core.Timer.STATE_PAUSED) - show_stop = (timer_state == core.Timer.STATE_RUNNING or - timer_state == core.Timer.STATE_PAUSED or - timer_state == core.Timer.STATE_FINISHED) - show_restart = (timer_state == core.Timer.STATE_RUNNING or - timer_state == core.Timer.STATE_PAUSED or - timer_state == core.Timer.STATE_FINISHED) - show_next_timer = ((timer_state == core.Timer.STATE_RUNNING or - timer_state == core.Timer.STATE_PAUSED or - timer_state == core.Timer.STATE_FINISHED) and - # Only show this popup menu item if it has a - # next_timer defined. Clever, huh? ;) - has_next_timer) - - show_presets_menu = (len(self._presets_store.get_model()) > 0) - show_separator = ( - show_presets_menu or - show_pause or - show_next_timer or - show_continue or - show_stop or - show_restart) - - to_hidden_str = lambda show: ('0', '1')[not show] - popup.set_prop('/commands/PauseTimer', 'hidden', to_hidden_str(show_pause)) - popup.set_prop('/commands/ContinueTimer', 'hidden', to_hidden_str(show_continue)) - popup.set_prop('/commands/StopTimer', 'hidden', to_hidden_str(show_stop)) - popup.set_prop('/commands/RestartTimer', 'hidden', to_hidden_str(show_restart)) - popup.set_prop('/commands/StartNextTimer', 'hidden', to_hidden_str(show_next_timer)) - popup.set_prop(TimerApplet._PRESETS_PATH, 'hidden', to_hidden_str(show_presets_menu)) - popup.set_prop('/popups/popup/Separator1', 'hidden', to_hidden_str(show_separator)) - - # Rebuild the Presets submenu - if popup.path_exists(TimerApplet._PRESETS_PLACEHOLDER_PATH): - popup.rm(TimerApplet._PRESETS_PLACEHOLDER_PATH) - popup.set_translate(TimerApplet._PRESETS_PATH, - '<placeholder name="%s"/>' % TimerApplet._PRESETS_PLACEHOLDER_NAME) - - preset_number = 1 - row_iter = self._presets_store.get_model().get_iter_first() - while row_iter is not None: - verb = ('Preset_%d' % preset_number) - preset_number += 1 - display_text = utils.get_preset_display_text(self._presets_store, row_iter) - node_xml = '<menuitem verb="%s" name="%s" label="%s"/>' % (verb, verb, display_text) - popup.set_translate(TimerApplet._PRESETS_PLACEHOLDER_PATH, node_xml) - popup.add_verb(verb, - self._on_presets_submenu_item_activated, - self._presets_store.get_model().get_path(row_iter)) - row_iter = self._presets_store.get_model().iter_next(row_iter) - - def _update_preferences_dialog(self): - self._preferences_dialog.props.show_remaining_time = \ - self._mateconf.get_bool(TimerApplet._SHOW_REMAINING_TIME_KEY) - self._preferences_dialog.props.play_sound = \ - self._mateconf.get_bool(TimerApplet._PLAY_SOUND_KEY) - self._preferences_dialog.props.use_custom_sound = \ - self._mateconf.get_bool(TimerApplet._USE_CUSTOM_SOUND_KEY) - self._preferences_dialog.props.show_popup_notification = \ - self._mateconf.get_bool(TimerApplet._SHOW_POPUP_NOTIFICATION_KEY) - self._preferences_dialog.props.show_pulsing_icon = \ - self._mateconf.get_bool(TimerApplet._SHOW_PULSING_ICON_KEY) - self._preferences_dialog.props.custom_sound_path = \ - self._mateconf.get_string(TimerApplet._CUSTOM_SOUND_PATH_KEY) - - ## Applet callbacks ## - - def _on_applet_change_background(self, applet, background_type, color, pixmap): - applet.set_style(None) - rc_style = gtk.RcStyle() - applet.modify_style(rc_style) - - if background_type == mateapplet.NO_BACKGROUND: - pass - elif background_type == mateapplet.COLOR_BACKGROUND: - applet.modify_bg(gtk.STATE_NORMAL, color) - elif background_type == mateapplet.PIXMAP_BACKGROUND: - style = applet.style.copy() - style.bg_pixmap[gtk.STATE_NORMAL] = pixmap - applet.set_style(style) - - def _on_applet_destroy(self, sender, data=None): - self._call_notify(show=False) - if self._timer.get_state() != core.Timer.STATE_IDLE: - self._timer.reset() # will stop timeout - self._mateconf.delete() - - ## Popup menu callbacks ## - - def _on_presets_submenu_item_activated(self, component, verb, row_path): - # Try hiding the Start Timer dialog, just in case it's open. - self._start_timer_dialog.hide() - row_iter = self._presets_store.get_model().get_iter(row_path) - (name, hours, minutes, seconds, command, next_timer, auto_start) = self._presets_store.get_preset(row_iter) - self._start_timer_with_settings(name, hours, minutes, seconds, command, - next_timer, auto_start) - - ## MateConf callbacks ## - - def _on_mateconf_changed(self, mateconf_value, data=None): - self._update_status_button() - self._update_preferences_dialog() - - ## PreferencesDialog callbacks ## - - def _on_prefs_show_time_changed(self, sender, show_time): - self._mateconf.set_bool(TimerApplet._SHOW_REMAINING_TIME_KEY, - show_time) - - def _on_prefs_play_sound_changed(self, sender, play_sound): - self._mateconf.set_bool(TimerApplet._PLAY_SOUND_KEY, - play_sound) - - def _on_prefs_use_custom_sound_changed(self, sender, use_custom_sound): - self._mateconf.set_bool(TimerApplet._USE_CUSTOM_SOUND_KEY, - use_custom_sound) - - def _on_prefs_show_pulsing_icon_changed(self, sender, show_pulsing_icon): - self._mateconf.set_bool(TimerApplet._SHOW_PULSING_ICON_KEY, - show_pulsing_icon) - - def _on_prefs_show_popup_notification_changed(self, sender, - show_popup_notification): - self._mateconf.set_bool(TimerApplet._SHOW_POPUP_NOTIFICATION_KEY, - show_popup_notification) - - def _on_prefs_custom_sound_path_changed(self, sender, custom_sound_path): - self._mateconf.set_string(TimerApplet._CUSTOM_SOUND_PATH_KEY, - custom_sound_path) - - ## Timer callbacks ## - - def _on_timer_time_changed(self, timer): - hours, minutes, seconds = utils.seconds_to_hms(timer.get_remaining_time()) - print 'Remaining time: %d, %d, %d' % (hours, minutes, seconds) - name = self._timer.get_name() - self._status_button.set_label(utils.construct_time_str(self._timer.get_remaining_time(), - show_all=False)) - - fraction_remaining = float(self._timer.get_remaining_time()) / self._timer.get_duration() - progress = min(1.0, max(0.0, 1.0 - fraction_remaining)) - self._status_button.set_progress(progress) - - if len(name) > 0: - # HH:MM:SS (<timer name>) - self._status_button.set_tooltip(_('%02d:%02d:%02d (%s)') % (hours, minutes, seconds, name)) - else: - # HH:MM:SS - self._status_button.set_tooltip(_('%02d:%02d:%02d') % (hours, minutes, seconds)) - - def _on_timer_state_changed(self, timer, data=None): - # TODO: - # Refactor me! - print 'State changed' - new_state = timer.get_state() - print ' new state: %d' % new_state - - # These actions should be done once upon a state change. - # That's why they're done here and not in self._update_status_button(); - # self._update_status_button() could be called multiple times - # while in the same state. - if new_state == core.Timer.STATE_FINISHED: - name = self._timer.get_name() - command = self._timer.get_command() - end_time = self._timer.get_end_time() - time_text = utils.get_display_text_from_datetime(end_time) - summary = None - message = None - if len(name) > 0: - # "<timer name>" Finished - summary = (_('"%s" Finished') % name) - - # "<timer name>" finished at <time> - message = (_('"%s" finished at %s') % (name, time_text)) - else: - summary = _('Timer Finished') - - # Timer finished at <time> - message = (_('Timer finished at %s') % time_text) - - - def reminder_message_func(): - elapsed_time = datetime.now() - end_time - message = None - if elapsed_time < timedelta(seconds=60): - message = ngettext('Timer finished about <b>%d second</b> ago', - 'Timer finished about <b>%d seconds</b> ago', - elapsed_time.seconds) % elapsed_time.seconds - else: - minutes = elapsed_time.seconds / 60 - message = ngettext('Timer finished about <b>%d minute</b> ago', - 'Timer finished about <b>%d minutes</b> ago', - minutes) % minutes - return message - - # TODO: - # FIXME: - # Reason for using a Python thread: - # To do all the procedures after timer has ended. If I don't do - # this then after the timer ended and it had an auto-start and next - # timer defined, it would directly switch without any notification. - # Trying time.sleep() doesn't work as expected; it correctly starts - # the next timer, but it doesn't show the notification and the - # rest. - class MyThread(threading.Thread): - def __init__(self, timer_instance): - threading.Thread.__init__(self) - self.timer = timer_instance - - def run(self): - print "Starting thread..." - print "Calling popup notification.", - self.timer._call_notify(summary, message, reminder_message_func) - print "Starting pulsing button.", - self.timer._start_pulsing_button() - print "Playing notification sound.", - self.timer._play_notification_sound() - print "Running custom command.", - self.timer._run_custom_command(command) - - print "Ending Thread..." - thread = MyThread(self) - thread.start() - thread.join() - - next_timer = self._timer.get_next_timer() - auto_start = self._timer.get_auto_start() - if auto_start and next_timer: - # Start next timer - self._stop_sound() - self._call_notify(show=False) - self._stop_pulsing_button() - self._start_next_timer() - elif not(auto_start) and next_timer: - self._status_button.props.sensitive = False - dialog_result = self._start_next_timer_dialog.get_response() - self._status_button.props.sensitive = True - if dialog_result: - # Start next timer - self._stop_sound() - self._call_notify(show=False) - self._stop_pulsing_button() - self._start_next_timer() - else: - self._stop_sound() - self._call_notify(show=False) - self._stop_pulsing_button() - - print "Updating status button..." - self._update_status_button() - print "Updating popup menu..." - self._update_popup_menu() - - ## StatusButton callbacks ## - - def _on_status_button_clicked(self, button, data=None): - current_state = self._timer.get_state() - if current_state == core.Timer.STATE_IDLE: - self._start_timer_dialog.show() - elif current_state == core.Timer.STATE_FINISHED: - self._timer.reset() - elif current_state == core.Timer.STATE_PAUSED: - # Temporarily disable status button while the Continue dialog is open. - self._status_button.props.sensitive = False - dialog_result = self._continue_dialog.get_response() - self._status_button.props.sensitive = True - if dialog_result == ui.ContinueTimerDialog.CONTINUE_TIMER: - self._timer.start() - elif dialog_result == ui.ContinueTimerDialog.STOP_TIMER: - self._timer.reset() - elif dialog_result == ui.ContinueTimerDialog.KEEP_PAUSED: - pass - else: - assert False - elif current_state == core.Timer.STATE_RUNNING: - self._timer.stop() - - ## StartTimerDialog callbacks ## - - def _on_start_dialog_clicked_start(self, sender, data=None): - (name, hours, minutes, seconds, command, next_timer, auto_start) = \ - self._start_timer_dialog.get_control_data() - self._start_timer_with_settings(name, hours, minutes, seconds, command, - next_timer, auto_start) - - def _on_start_dialog_clicked_manage_presets(self, sender, data=None): - self._manage_presets_dialog.show() - - def _on_start_dialog_clicked_save(self, sender, name, - hours, minutes, seconds, command, - next_timer, auto_start, data=None): - self._presets_store.add_preset(name, hours, minutes, seconds, command, - next_timer, auto_start) - - def _on_start_dialog_clicked_preset(self, sender, row_path, data=None): - row_iter = self._presets_store.get_model().get_iter(row_path) - (name, hours, minutes, seconds, command, next_timer, auto_start) = \ - self._presets_store.get_preset(row_iter) - self._start_timer_dialog.set_name_and_duration(name, hours, minutes, - seconds, command, - next_timer, auto_start) - - def _on_start_dialog_double_clicked_preset(self, sender, row_path, data=None): - """Preset is double-clicked. Start the selected preset, and hide the - dialog.""" - row_iter = self._presets_store.get_model().get_iter(row_path) - (name, hours, minutes, seconds, command, next_timer, auto_start) = \ - self._presets_store.get_preset(row_iter) - self._start_timer_with_settings(name, hours, minutes, seconds, command, - next_timer, auto_start) - self._start_timer_dialog.hide() - - ## Private methods ## - - def _start_timer_with_settings(self, name, hours, minutes, seconds, - command, next_timer, auto_start): - print "Resetting timer" - if self._timer.get_state() != core.Timer.STATE_IDLE: - self._timer.reset() - self._timer.set_duration(utils.hms_to_seconds(hours, minutes, seconds)) - self._timer.set_name(name) - self._timer.set_command(command) - self._timer.set_next_timer(next_timer) - self._timer.set_auto_start(auto_start) - self._timer.start() - - def _restart_timer(self): - self._timer.reset() - self._timer.start() - - def _start_next_timer(self): - """Start next timer, if defined.""" - next_timer = self._timer.get_next_timer() - for row in self._presets_store.get_model(): - #print dir(row) - if str(row[0]) == next_timer: - (name, hours, minutes, seconds, command, next_timer, auto_start) = \ - self._presets_store.get_preset(row.iter) - break - print "Starting timer with settings: ", - print (name, hours, minutes, seconds, command, next_timer, auto_start) - self._start_timer_with_settings(name, hours, minutes, seconds, command, - next_timer, auto_start) - - - def _play_notification_sound(self): - if not self._mateconf.get_bool(TimerApplet._PLAY_SOUND_KEY): - return - - sound_path = config.DEFAULT_SOUND_PATH - if self._mateconf.get_bool(TimerApplet._USE_CUSTOM_SOUND_KEY): - sound_path = self._mateconf.get_string(TimerApplet._CUSTOM_SOUND_PATH_KEY) - - print 'Playing notification sound: "%s"' % str(sound_path) - self._play_sound(sound_path) - print 'Started playing notification sound.' - - def _play_sound(self, file_path): - if not file_path: - print 'Invalid path to sound file' - return - self._gst_playbin.set_state(gst.STATE_NULL) - sound_uri = 'file://' + file_path - print 'Using GStreamer to play: ' + sound_uri - self._gst_playbin.set_property('uri', sound_uri) - self._gst_playbin.set_state(gst.STATE_PLAYING) - - def _run_custom_command(self, command): - if command: - print "Running custom command: " + command - try: - subprocess.call(shlex.split(command)) - except OSError: - print "... failed. Command not found." - - def _stop_sound(self): - self._gst_playbin.set_state(gst.STATE_NULL) - - def _start_pulsing_button(self): - if self._mateconf.get_bool(TimerApplet._SHOW_PULSING_ICON_KEY): - self._status_button.start_pulsing() - - def _stop_pulsing_button(self): - self._status_button.stop_pulsing() - - def _show_about_dialog(self): - self._about_dialog.run() - self._about_dialog.hide() - - def _call_notify(self, summary=None, message=None, - reminder_message_func=None, show=True): - if self._mateconf.get_bool(TimerApplet._SHOW_POPUP_NOTIFICATION_KEY): - if show: - self._notifier.begin(summary, message, reminder_message_func) - else: - self._notifier.end() diff --git a/timer-applet/src/timerapplet/controllers/TimerManagerService.py b/timer-applet/src/timerapplet/controllers/TimerManagerService.py deleted file mode 100644 index b33155a8..00000000 --- a/timer-applet/src/timerapplet/controllers/TimerManagerService.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import dbus -import dbus.service - -DBUS_INTERFACE_NAMESPACE = 'net.launchpad.timerapplet.TimerApplet.TimerManager' - -class TimerManagerService(dbus.service.Object): - def __init__(self, bus_name, object_path): - dbus.service.Object.__init__(self, - dbus.service.BusName(bus_name, bus=dbus.SessionBus()), - object_path) - self._timer_id_list = [] - - def create_and_register_timer_id(self): - timer_id = str(uuid.uuid4()) - self.register_timer_id(timer_id) - return timer_id - - def register_timer_id(self, timer_id): - self._timer_id_list.append(timer_id) - - def unregister_timer_id(self, timer_id): - self._timer_id_list.remove(timer_id) - - @dbus.service.method(dbus_interface=DBUS_INTERFACE_NAMESPACE, out_signature='as') - def GetTimerIDList(self): - return self._timer_id_list diff --git a/timer-applet/src/timerapplet/controllers/TimerService.py b/timer-applet/src/timerapplet/controllers/TimerService.py deleted file mode 100644 index a4b25b8a..00000000 --- a/timer-applet/src/timerapplet/controllers/TimerService.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import dbus -import dbus.service -from timerapplet import core -from timerapplet import utils - -DBUS_INTERFACE_NAMESPACE = 'net.launchpad.timerapplet.TimerApplet.Timer' - -class TimerService(dbus.service.Object): - def __init__(self, bus_name, object_path, timer): - dbus.service.Object.__init__(self, - dbus.service.BusName(bus_name, bus=dbus.SessionBus()), - object_path) - self._timer = timer - - @dbus.service.method(dbus_interface=DBUS_INTERFACE_NAMESPACE, in_signature='siii') - def Start(self, name, hours, minutes, seconds): - if self._timer.get_state() != core.Timer.STATE_IDLE: - self._timer.reset() - self._timer.set_duration(utils.hms_to_seconds(hours, minutes, seconds)) - self._timer.set_name(name) - self._timer.start() - - @dbus.service.method(dbus_interface=DBUS_INTERFACE_NAMESPACE) - def Stop(self): - if self._timer.get_state() != core.Timer.STATE_IDLE: - self._timer.reset() - - @dbus.service.method(dbus_interface=DBUS_INTERFACE_NAMESPACE) - def PauseContinue(self): - if self._timer.get_state() == core.Timer.STATE_RUNNING: - self._timer.stop() - elif self._timer.get_state() == core.Timer.STATE_PAUSED: - self._timer.start() diff --git a/timer-applet/src/timerapplet/controllers/__init__.py b/timer-applet/src/timerapplet/controllers/__init__.py deleted file mode 100644 index 471dd256..00000000 --- a/timer-applet/src/timerapplet/controllers/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from GlobalController import GlobalController -from TimerApplet import TimerApplet -from TimerManagerService import TimerManagerService -from TimerService import TimerService diff --git a/timer-applet/src/timerapplet/core/AppletMateConfWrapper.py b/timer-applet/src/timerapplet/core/AppletMateConfWrapper.py deleted file mode 100644 index 8e4cecb5..00000000 --- a/timer-applet/src/timerapplet/core/AppletMateConfWrapper.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from os import path -import mateconf - -class AppletMateConfWrapper(object): - def __init__(self, applet, schema_path, standalone_key): - object.__init__(self) - self._connection_ids = [] - - self._client = mateconf.client_get_default() - - # Get preferences key path for the given applet instance. - self._base_path = applet.get_preferences_key() - if self._base_path is not None: - # Apply the schema to the applet instance preferences key. - applet.add_preferences(schema_path) - else: - # NOTE: Don't need to apply schema here because the Timer Applet schema file - # already specifies that the schema be automatically applied to the standalone key. - - self._base_path = standalone_key - - # Applet would usually do this for us, but since we're running in standalone mode, - # we have to do this ourselves in order to receive MateConf change notifications. - self._client.add_dir(self._base_path, mateconf.CLIENT_PRELOAD_RECURSIVE) - - print 'Base prefs path = %s' % self._base_path - - def get_base_path(self): - return self._base_path - - def add_notification(self, relative_key, callback, data=None): - """Register for notifications of changes to the given preference key. - - relative_key should be relative to the applet's base preferences key path. - callback should look like: callback(MateConfValue, data=None) - """ - connection_id = self._client.notify_add(self._get_full_path(relative_key), - self._notification_callback, (callback, data)) - self._connection_ids.append(connection_id) - - def get_string(self, relative_key): - return self._client.get_string(self._get_full_path(relative_key)) - - def get_bool(self, relative_key): - return self._client.get_bool(self._get_full_path(relative_key)) - - def set_string(self, relative_key, val): - self._client.set_string(self._get_full_path(relative_key), val) - - def set_bool(self, relative_key, val): - self._client.set_bool(self._get_full_path(relative_key), val) - - def delete(self): - for connection_id in self._connection_ids: - self._client.notify_remove(connection_id) - self._connection_ids = [] - - def _notification_callback(self, client, cnxn_id, entry, data=None): - (callback, real_data) = data - - # mateconf_value is of type MateConfValue (mateconf.Value) - mateconf_value = entry.get_value() - - # Ignore when mateconf_value is None because that - # means that the settings are being removed - # because the applet has been removed from - # the panel. - if mateconf_value != None: - callback(mateconf_value, real_data) - - def _get_full_path(self, relative_key): - return path.join(self._base_path, relative_key) - diff --git a/timer-applet/src/timerapplet/core/Makefile.am b/timer-applet/src/timerapplet/core/Makefile.am deleted file mode 100644 index 6c974866..00000000 --- a/timer-applet/src/timerapplet/core/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -moduledir = $(pythondir)/timerapplet/core -module_PYTHON = \ - __init__.py \ - AppletMateConfWrapper.py \ - PresetsStore.py \ - Timer.py diff --git a/timer-applet/src/timerapplet/core/PresetsStore.py b/timer-applet/src/timerapplet/core/PresetsStore.py deleted file mode 100644 index 6c9323b7..00000000 --- a/timer-applet/src/timerapplet/core/PresetsStore.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# Copyright (C) 2010 Kenny Meyer <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -try: - from xml.etree import ElementTree as et -except: - from elementtree import ElementTree as et - -import os -from os import path -import gobject -import gtk -import timerapplet.utils as utils - -from timerapplet.utils import (serialize_bool, - deserialize_bool, - seconds_to_hms, - hms_to_seconds) -from timerapplet.defs import VERSION - -class PersistentStore(gtk.ListStore): - def __init__(self, load_func, save_func, *args): - gtk.ListStore.__init__(self, *args) - load_func(self) - - self.connect('row-deleted', lambda model, row_path: save_func(self)) - self.connect('row-changed', lambda model, row_path, row_iter: save_func(self)) - -class PresetsStore(gobject.GObject): - (_NAME_COL, - _HOURS_COL, - _MINUTES_COL, - _SECONDS_COL, - _COM_COL, - _NEXT_COL, - _AUTO_START_COL) = xrange(7) - - def __init__(self, filename): - object.__init__(self) - self._model = PersistentStore(lambda model: PresetsStore._load_presets(model, filename), - lambda model: PresetsStore._save_presets(model, filename), - gobject.TYPE_STRING, - gobject.TYPE_INT, - gobject.TYPE_INT, - gobject.TYPE_INT, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_BOOLEAN, - ) - - def get_model(self): - """Return GtkTreeModel. - - Should not rely on it being any particular subtype of GtkTreeModel. - - """ - return self._model - - def get_preset(self, row_iter): - return self._model.get(row_iter, - PresetsStore._NAME_COL, - PresetsStore._HOURS_COL, - PresetsStore._MINUTES_COL, - PresetsStore._SECONDS_COL, - PresetsStore._COM_COL, - PresetsStore._NEXT_COL, - PresetsStore._AUTO_START_COL, - ) - - def add_preset(self, name, hours, minutes, seconds, command, next_timer, - auto_start): - self._model.append((name, hours, minutes, seconds, command, next_timer, - auto_start)) - - def modify_preset(self, row_iter, name, hours, minutes, seconds, command, - next_timer, auto_start): - self._model.set(row_iter, - PresetsStore._NAME_COL, name, - PresetsStore._HOURS_COL, hours, - PresetsStore._MINUTES_COL, minutes, - PresetsStore._SECONDS_COL, seconds, - PresetsStore._COM_COL, command, - PresetsStore._NEXT_COL, next_timer, - PresetsStore._AUTO_START_COL, auto_start - ) - - def remove_preset(self, row_iter): - self._model.remove(row_iter) - - def preset_name_exists_case_insensitive(self, preset_name): - preset_name = preset_name.lower() - for preset in self._model: - if preset_name == preset[PresetsStore._NAME_COL].lower(): - return True - return False - - def _load_presets(model, file_path): - try: - tree = et.parse(file_path) - except: - return - - root = tree.getroot() - - for node in root: - name = node.get('name') - (hours, minutes, seconds) = seconds_to_hms(int(node.get('duration'))) - command = node.get('command') - next_timer = node.get('next_timer') - auto_start = node.get('auto_start') - model.append((name, hours, minutes, seconds, command, next_timer, - deserialize_bool(auto_start))) - _load_presets = staticmethod(_load_presets) - - def _save_presets(model, file_path): - root = et.Element('timerapplet') - root.set('version', VERSION) - - def add_xml_node(model, path, row_iter): - (name, hours, minutes, seconds, command, next_timer, auto_start) = \ - model.get(row_iter, - PresetsStore._NAME_COL, - PresetsStore._HOURS_COL, - PresetsStore._MINUTES_COL, - PresetsStore._SECONDS_COL, - PresetsStore._COM_COL, - PresetsStore._NEXT_COL, - PresetsStore._AUTO_START_COL - ) - node = et.SubElement(root, 'preset') - node.set('name', name) - node.set('duration', str(hms_to_seconds(hours, minutes, seconds))) - node.set('command', command or '') - node.set('next_timer', next_timer or '') - node.set('auto_start', serialize_bool(auto_start)) - - model.foreach(add_xml_node) - tree = et.ElementTree(root) - - file_dir = path.dirname(file_path) - if not path.exists(file_dir): - print 'Creating config directory: %s' % file_dir - os.makedirs(file_dir, 0744) - tree.write(file_path) - _save_presets = staticmethod(_save_presets) - diff --git a/timer-applet/src/timerapplet/core/Timer.py b/timer-applet/src/timerapplet/core/Timer.py deleted file mode 100644 index d2f8c695..00000000 --- a/timer-applet/src/timerapplet/core/Timer.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# Copyright (C) 2010 Kenny Meyer <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import datetime -import time -import gobject - -class Timer(gobject.GObject): - (STATE_IDLE, STATE_RUNNING, STATE_PAUSED, STATE_FINISHED) = xrange(4) - - __gsignals__ = {'time-changed': - (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - 'state-changed': - (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())} - - def __init__(self): - gobject.GObject.__init__(self) - self._state = Timer.STATE_IDLE - self._duration_seconds = 0 - self._remaining_seconds = 0 - self._end_time = 0 - self._name = '' - self._command = '' - self._next_timer = '' - self._auto_start = False - - def set_duration(self, seconds): - """Set the duration of the timer in seconds.""" - assert self._state == Timer.STATE_IDLE - self._duration_seconds = seconds - - def get_duration(self): - """Return the duration of the timer in seconds.""" - return self._duration_seconds - - def set_name(self, name): - """Set the name of the timer.""" - assert self._state == Timer.STATE_IDLE - self._name = name - - def get_name(self): - """Return the name of the timer.""" - return self._name - - def set_command(self, command): - """Set the command to run of the timer.""" - assert self._state == Timer.STATE_IDLE - self._command = command - - def get_command(self): - """Return the name of the command of the timer.""" - return self._command - - def set_next_timer(self, timer): - """Set the next timeer of the timer.""" - assert self._state == Timer.STATE_IDLE - self._next_timer = timer - - def get_next_timer(self): - """Get the next timer of the timer.""" - return self._next_timer - - def set_auto_start(self, auto_start): - """Set the auto-start value of the timer.""" - assert self._state == Timer.STATE_IDLE - self._auto_start = auto_start - - def get_auto_start(self): - """Get the auto-start value.""" - return self._auto_start - - def start(self): - """Start or resume the timer. - - This method should only be called when the timer is IDLE or PAUSED. - - """ - assert self._state == Timer.STATE_IDLE or self._state == Timer.STATE_PAUSED - self._timer_transition_to_state(Timer.STATE_RUNNING) - - def stop(self): - """Pause the timer. - - This method should only be called when the timer is RUNNING. - - """ - assert self._state == Timer.STATE_RUNNING - self._timer_transition_to_state(Timer.STATE_PAUSED) - - def reset(self): - """Reset the timer. - - This method should only be called when the timer is not IDLE. - - """ - assert self._state != Timer.STATE_IDLE - self._timer_transition_to_state(Timer.STATE_IDLE) - - def get_state(self): - """Return the current state.""" - return self._state - - def get_remaining_time(self): - """Return the remaining time in seconds.""" - return min(self._duration_seconds, max(0, self._remaining_seconds)) - - def get_end_time(self): - """Return a datetime object representing the end time. - - This method should only be called when the timer is RUNNING or FINISHED. - - """ - assert self._state == Timer.STATE_RUNNING or self._state == Timer.STATE_FINISHED - return datetime.datetime.fromtimestamp(self._end_time) - - def _timer_set_state(self, state): - self._state = state - self.emit('state-changed') - - def _timer_transition_to_state(self, dest_state): - cur_time = int(time.time()) - - if dest_state == Timer.STATE_IDLE: - self._end_time = 0 - self._set_remaining_time(self._duration_seconds) - elif dest_state == Timer.STATE_RUNNING: - assert self._duration_seconds >= 0 - - if self._state == Timer.STATE_IDLE: - self._end_time = cur_time + self._duration_seconds - self._set_remaining_time(self._duration_seconds) - elif self._state == Timer.STATE_PAUSED: - self._end_time = cur_time + self._remaining_seconds - - gobject.timeout_add(500, self._on_timeout) - elif dest_state == Timer.STATE_PAUSED: - self._set_remaining_time(self._end_time - cur_time) - self._end_time = 0 - elif dest_state == Timer.STATE_FINISHED: - pass - else: - assert False - - self._timer_set_state(dest_state) - - def _on_timeout(self): - if self._state != Timer.STATE_RUNNING: - return False # remove timeout source - - new_remaining = self._end_time - int(time.time()) - if self._remaining_seconds != new_remaining: - self._set_remaining_time(new_remaining) - - if self._remaining_seconds < 0: - self._timer_transition_to_state(Timer.STATE_FINISHED) - return False # remove timeout source - return True # keep timeout source - - def _set_remaining_time(self, new_remaining): - self._remaining_seconds = new_remaining - self.emit('time-changed') diff --git a/timer-applet/src/timerapplet/core/__init__.py b/timer-applet/src/timerapplet/core/__init__.py deleted file mode 100644 index 257837d5..00000000 --- a/timer-applet/src/timerapplet/core/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from Timer import Timer -from PresetsStore import PresetsStore -from AppletMateConfWrapper import AppletMateConfWrapper diff --git a/timer-applet/src/timerapplet/defs.py.in b/timer-applet/src/timerapplet/defs.py.in deleted file mode 100644 index 55087654..00000000 --- a/timer-applet/src/timerapplet/defs.py.in +++ /dev/null @@ -1,7 +0,0 @@ -PACKAGE = '@PACKAGE@' -VERSION = '@VERSION@' -GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@' -LOCALE_DIR = '@LOCALEDIR@' -RESOURCES_DIR = '@RESOURCESDIR@' -IMAGES_DIR = '@IMAGESDIR@' - diff --git a/timer-applet/src/timerapplet/logger.py b/timer-applet/src/timerapplet/logger.py deleted file mode 100644 index 489ee9c4..00000000 --- a/timer-applet/src/timerapplet/logger.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2010 Kenny Meyer <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import logging - -logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(levelname)-8s %(message)s', - datefmt='%a, %d %b %Y %H:%M:%S', - filename='/tmp/myapp.log', - filemode='w') diff --git a/timer-applet/src/timerapplet/ui/AddEditPresetDialog.py b/timer-applet/src/timerapplet/ui/AddEditPresetDialog.py deleted file mode 100644 index ce9d0aee..00000000 --- a/timer-applet/src/timerapplet/ui/AddEditPresetDialog.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gtk -import gtk.glade as glade -from DurationChooser import DurationChooser - -class AddEditPresetDialog(object): - def __init__(self, glade_file_name, title, name_validator_func, - name='', hours=0, minutes=0, seconds=0, command='', - next_timer='', auto_start=False): - self._valid_name_func = name_validator_func - - glade_widgets = glade.XML(glade_file_name, 'add_edit_preset_dialog') - self._dialog = glade_widgets.get_widget('add_edit_preset_dialog') - self._ok_button = glade_widgets.get_widget('ok_button') - self._cancel_button = glade_widgets.get_widget('cancel_button') - self._name_entry = glade_widgets.get_widget('name_entry') - duration_chooser_container = glade_widgets.get_widget('duration_chooser_container') - self._duration_chooser = DurationChooser(gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)) - self._command_entry = glade_widgets.get_widget('command_entry') - self._next_timer_entry = glade_widgets.get_widget('next_timer_entry') - self._auto_start_check = glade_widgets.get_widget('auto_start_check') - - duration_chooser_container.pack_start(self._duration_chooser) - - self._dialog.set_title(title) - self._dialog.set_default_response(gtk.RESPONSE_OK) - self._name_entry.set_text(name) - self._command_entry.set_text(command) - self._duration_chooser.set_duration(hours, minutes, seconds) - self._next_timer_entry.set_text(next_timer) - self._auto_start_check.set_active(auto_start) - - self._name_entry.connect('changed', lambda entry: self._check_for_valid_save_preset_input()) - self._duration_chooser.connect('duration-changed', - lambda chooser: self._check_for_valid_save_preset_input()) - self._duration_chooser.show() - - def _non_zero_duration(self): - (hours, minutes, seconds) = self._duration_chooser.get_duration() - return (hours > 0 or minutes > 0 or seconds > 0) - - def _check_for_valid_save_preset_input(self): - self._ok_button.props.sensitive = (self._non_zero_duration() and - self._valid_name_func(self._name_entry.get_text())) - - ## Callback for saving ## - - def get_preset(self): - self._check_for_valid_save_preset_input() - result = self._dialog.run() - self._dialog.hide() - if result == gtk.RESPONSE_OK: - (hours, minutes, seconds) = self._duration_chooser.get_duration() - cmd = self._command_entry.get_text() - next_timer = self._next_timer_entry.get_text() - auto_start = self._auto_start_check.get_active() - return (self._name_entry.get_text(), hours, minutes, seconds, cmd, - next_timer, auto_start) - else: - return None diff --git a/timer-applet/src/timerapplet/ui/ContinueTimerDialog.py b/timer-applet/src/timerapplet/ui/ContinueTimerDialog.py deleted file mode 100644 index 5353139f..00000000 --- a/timer-applet/src/timerapplet/ui/ContinueTimerDialog.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from gettext import gettext as _ -import gtk - -class ContinueTimerDialog(object): - (STOP_TIMER, KEEP_PAUSED, CONTINUE_TIMER) = xrange(3) - - def __init__(self, glade_file_name, header_text, body_text): - self._dialog = gtk.Dialog(_('Continue Timer'), - None, - gtk.DIALOG_DESTROY_WITH_PARENT, - (_('_Stop Timer'), gtk.RESPONSE_NO, - _('_Keep Paused'), gtk.RESPONSE_CLOSE, - _('_Continue Timer'), gtk.RESPONSE_YES)) - self._dialog.props.border_width = 6 - self._dialog.props.has_separator = False - self._dialog.props.resizable = False - self._dialog.vbox.props.spacing = 12 - self._dialog.set_default_response(gtk.RESPONSE_YES) - - hbox = gtk.HBox(False, 0) - hbox.props.spacing = 12 - hbox.props.border_width = 6 - - image = gtk.image_new_from_stock(gtk.STOCK_DIALOG_QUESTION, gtk.ICON_SIZE_DIALOG) - image.props.yalign = 0.0 - - label = gtk.Label('<span weight="bold" size="larger">%s</span>\n\n%s' % (header_text, body_text)) - label.props.use_markup = True - label.props.wrap = True - label.props.yalign = 0.0 - - hbox.pack_start(image, False, False, 0) - hbox.pack_start(label, False, False, 0) - self._dialog.vbox.pack_start(hbox, False, False, 0) - - hbox.show_all() - - def get_response(self): - dialog_result = self._dialog.run() - self._dialog.hide() - if dialog_result == gtk.RESPONSE_YES: - return ContinueTimerDialog.CONTINUE_TIMER - elif dialog_result == gtk.RESPONSE_NO: - return ContinueTimerDialog.STOP_TIMER - else: - return ContinueTimerDialog.KEEP_PAUSED - diff --git a/timer-applet/src/timerapplet/ui/DurationChooser.py b/timer-applet/src/timerapplet/ui/DurationChooser.py deleted file mode 100644 index bd8d35ae..00000000 --- a/timer-applet/src/timerapplet/ui/DurationChooser.py +++ /dev/null @@ -1,166 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from gettext import gettext as _ -import math -import gobject -import gtk - -class DurationChooser(gtk.VBox): - __gsignals__ = {'duration-changed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())} - MAX_HOURS = 48 - MAX_MINUTES = 999 - MAX_SECONDS = 999 - - def __init__(self, size_group): - gtk.VBox.__init__(self, False, 6) - - self._hours_spin = self._add_row(_('_Hours:'), - size_group, - DurationChooser.MAX_HOURS) - self._minutes_spin = self._add_row(_('_Minutes:'), - size_group, - DurationChooser.MAX_MINUTES) - self._seconds_spin = self._add_row(_('_Seconds:'), - size_group, - DurationChooser.MAX_SECONDS) - - def get_duration(self): - """Return numerical representations of the values in the spinbuttons. - - This method does not just call get_value_as_int() on each spinbutton because - get_value_as_int() does not return the most up-to-date value if the user is - in the middle of editing the value in a spinbutton. Instead, it actually - returns the value previously "confirmed" for the spinbutton (for example, - by moving focus to another widget). - - Example: User starts with all spinboxes set to 0. He types 5 in 'Minutes' and - immediately uses the keyboard to activate the 'Save as Preset' button. Because - the user never moved focus out of the spinbutton, get_value_as_int() will report - the previous value of 0, and the saved preset will not have the expected duration - of 5 minutes. - - If a particular spinbutton is empty or contains a non-float value, then this method - will report its value as zero. - - Returns a tuple in this format: (hours, minutes, seconds) - - """ - hours_str = self._hours_spin.props.text - minutes_str = self._minutes_spin.props.text - seconds_str = self._seconds_spin.props.text - hours = 0 - minutes = 0 - seconds = 0 - - try: - hours = float(hours_str) - except TypeError: - pass - except ValueError: - pass - - try: - minutes = float(minutes_str) - except TypeError: - pass - except ValueError: - pass - - try: - seconds = float(seconds_str) - except TypeError: - pass - except ValueError: - pass - - minutes_fraction = minutes - int(minutes) - hours_fraction = hours - int(hours) - - # Distribute overflow from seconds to minutes to hours. - if seconds > 59: - minutes = math.floor(seconds / 60) - seconds = seconds % 60 - if minutes > 59: - hours = math.floor(minutes / 60) - minutes = minutes % 60 - if hours > DurationChooser.MAX_HOURS: - hours = DurationChooser.MAX_HOURS - - # Distribute fractions. - if hours_fraction > 0: - minutes = int(hours_fraction * 60) - if minutes_fraction > 0: - seconds = int(minutes_fraction * 60) - - return (int(hours), int(minutes), int(seconds)) - - def set_duration(self, hours, minutes, seconds): - self._hours_spin.set_value(hours) - self._minutes_spin.set_value(minutes) - self._seconds_spin.set_value(seconds) - - def normalize_fields(self): - (hours, minutes, seconds) = self.get_duration() - self._hours_spin.set_value(hours) - self._minutes_spin.set_value(minutes) - self._seconds_spin.set_value(seconds) - - def clear(self): - self._hours_spin.set_value(0) - self._minutes_spin.set_value(0) - self._seconds_spin.set_value(0) - - def focus_hours(self): - self._hours_spin.grab_focus() - - def _add_row(self, row_label_str, size_group, max_spin_val): - row_hbox = gtk.HBox(False, 6) - - label = gtk.Label(row_label_str) - label.set_property('xalign', 0.0) - label.set_property('use-underline', True) - size_group.add_widget(label) - - spin_adj = gtk.Adjustment(0, 0, max_spin_val, 1, 1, 0) - spin_button = gtk.SpinButton(spin_adj, 1.0, 0) - spin_button.props.activates_default = True - spin_button.props.numeric = False - spin_button.props.update_policy = gtk.UPDATE_IF_VALID - - label.set_mnemonic_widget(spin_button) - - row_hbox.pack_start(label, False, False, 0) - row_hbox.pack_start(spin_button, True, True, 0) - self.pack_start(row_hbox, False, False, 0) - - spin_button.connect('changed', self._on_spin_button_val_changed) - spin_button.connect('focus-out-event', self._on_spin_button_focus_out) - spin_button.connect('activate', self._on_spin_button_activate) - - label.show() - spin_button.show() - row_hbox.show() - return spin_button - - def _on_spin_button_val_changed(self, spin_button): - self.emit('duration-changed') - - def _on_spin_button_focus_out(self, spin_button, event): - self.normalize_fields() - - def _on_spin_button_activate(self, entry): - self.normalize_fields() diff --git a/timer-applet/src/timerapplet/ui/Makefile.am b/timer-applet/src/timerapplet/ui/Makefile.am deleted file mode 100644 index 0021823e..00000000 --- a/timer-applet/src/timerapplet/ui/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -moduledir = $(pythondir)/timerapplet/ui -module_PYTHON = \ - __init__.py \ - AddEditPresetDialog.py \ - ContinueTimerDialog.py \ - DurationChooser.py \ - ManagePresetsDialog.py \ - Notifier.py \ - PieMeter.py \ - PreferencesDialog.py \ - PulseButton.py \ - ScrollableButtonList.py \ - StartTimerDialog.py \ - StartNextTimerDialog.py \ - StatusButton.py diff --git a/timer-applet/src/timerapplet/ui/ManagePresetsDialog.py b/timer-applet/src/timerapplet/ui/ManagePresetsDialog.py deleted file mode 100644 index 80f97bdb..00000000 --- a/timer-applet/src/timerapplet/ui/ManagePresetsDialog.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gobject -import gtk -import gtk.glade as glade - -class ManagePresetsDialog(gobject.GObject): - __gsignals__ = {'clicked-add': - (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - 'clicked-edit': - (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), - 'clicked-remove': - (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))} - - def __init__(self, glade_file_name, presets_store, preset_display_func): - gobject.GObject.__init__(self) - - glade_widgets = glade.XML(glade_file_name, 'manage_presets_dialog') - self._dialog = glade_widgets.get_widget('manage_presets_dialog') - self._presets_view = glade_widgets.get_widget('presets_view') - self._delete_button = glade_widgets.get_widget('delete_button') - self._edit_button = glade_widgets.get_widget('edit_button') - self._add_button = glade_widgets.get_widget('add_button') - - self._presets_view.set_model(presets_store) - renderer = gtk.CellRendererText() - col = gtk.TreeViewColumn('Preset', renderer) - - def preset_cell_data_func(col, cell, model, row_iter, user_data=None): - cell.props.text = preset_display_func(row_iter) - - col.set_cell_data_func(renderer, preset_cell_data_func) - self._presets_view.append_column(col) - - self._dialog.connect('response', self._on_dialog_response) - self._dialog.connect('delete-event', self._dialog.hide_on_delete) - self._presets_view.get_selection().connect('changed', lambda selection: self._update_button_states()) - self._delete_button.connect('clicked', self._on_delete_button_clicked) - self._edit_button.connect('clicked', self._on_edit_button_clicked) - self._add_button.connect('clicked', self._on_add_button_clicked) - - self._update_button_states() - self._dialog.set_default_size(300, 220) - - def show(self): - self._dialog.present() - - def _get_selected_path(self): - selection = self._presets_view.get_selection() - (model, selection_iter) = selection.get_selected() - return model.get_path(selection_iter) - - def _update_button_states(self): - selection = self._presets_view.get_selection() - num_selected = selection.count_selected_rows() - self._delete_button.props.sensitive = num_selected >= 1 - self._edit_button.props.sensitive = num_selected == 1 - - def _on_delete_button_clicked(self, button): - row_path = self._get_selected_path() - self.emit('clicked-remove', row_path) - - def _on_edit_button_clicked(self, button): - row_path = self._get_selected_path() - self.emit('clicked-edit', row_path) - - def _on_add_button_clicked(self, button): - self.emit('clicked-add') - - def _on_dialog_response(self, dialog, response_id): - dialog.hide() - diff --git a/timer-applet/src/timerapplet/ui/Notifier.py b/timer-applet/src/timerapplet/ui/Notifier.py deleted file mode 100644 index 91db1517..00000000 --- a/timer-applet/src/timerapplet/ui/Notifier.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gobject -import pynotify - -class Notifier(object): - _NOTIFICATION_REDISPLAY_INTERVAL_SECONDS = 60 - - def __init__(self, app_name, icon, attach): - self._icon = icon - self._attach = attach - self._notify = None - self._handler_id = None - self._timeout_id = None - - if not pynotify.is_initted(): - pynotify.init(app_name) - - def begin(self, summary, body, get_reminder_message_func): - # NOTE: This callback wrapper is to workaround an API-breaking change present in - # the version of libmatenotify used by Fedora 10. The API break adds an additional - # 'reason' parameter to the callback signature. This was fixed before - # the latest official release of libmatenotify, but it looks like Fedora 10 - # is using an unofficial libmatenotify build that still contains the API-breaking change. - def closed_callback_wrapper(notification, reason_UNUSED=None): - self._on_notification_closed(notification, get_reminder_message_func) - - self.end() - self._notify = pynotify.Notification(summary, body, self._icon) - self._handler_id = self._notify.connect('closed', closed_callback_wrapper) - self._notify.show() - - def end(self): - if self._notify is not None: - if self._timeout_id is not None: - gobject.source_remove(self._timeout_id) - self._timeout_id = None - self._notify.disconnect(self._handler_id) - self._handler_id = None - try: - self._notify.close() - except gobject.GError: - # Throws a GError exception if the notification bubble has already been closed. - # Ignore the exception. - pass - self._notify = None - - def _on_notification_closed(self, notification, get_reminder_message_func): - self._timeout_id = gobject.timeout_add(Notifier._NOTIFICATION_REDISPLAY_INTERVAL_SECONDS * 1000, - self._on_notification_redisplay_timeout, - get_reminder_message_func) - - def _on_notification_redisplay_timeout(self, get_reminder_message_func): - message = get_reminder_message_func() - self._notify.props.body = message - self._notify.show() - - self._timeout_id = None - return False diff --git a/timer-applet/src/timerapplet/ui/PieMeter.py b/timer-applet/src/timerapplet/ui/PieMeter.py deleted file mode 100644 index 9bec5e5c..00000000 --- a/timer-applet/src/timerapplet/ui/PieMeter.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import math -import gobject -import gtk - -class PieMeter(gtk.Image): - _DEFAULT_SIZE = 24 - - def __init__(self): - gtk.Image.__init__(self) - self._progress = 0.0 - self._fill_color = (0.0, 1.0, 0.0) - - def set_progress(self, progress): - assert progress >= 0.0 - assert progress <= 1.0 - self._progress = progress - if self.window is not None: - self.window.invalidate_rect(self.allocation, True) - - def set_fill_color(self, red, green, blue): - assert 0.0 <= red <= 1.0 - assert 0.0 <= green <= 1.0 - assert 0.0 <= blue <= 1.0 - self._fill_color = (red, green, blue) - - if self.window is not None: - self.window.invalidate_rect(self.allocation, True) - - def do_size_request(self, requisition): - requisition.width = PieMeter._DEFAULT_SIZE - requisition.height = PieMeter._DEFAULT_SIZE - - def do_expose_event(self, event): - context = event.window.cairo_create() - - rect = self.allocation - x = rect.x + (rect.width / 2) - y = rect.y + (rect.height / 2) - radius = (min(rect.width, rect.height) / 2) - - # Draw background circle - context.arc(x, y, radius, 0, 2 * math.pi) - context.set_source_rgba(0.8, 0.8, 0.8) - context.fill() - - # Draw pie - context.arc(x, y, radius, (-0.5 * math.pi) + self._progress * 2 * math.pi, 1.5 * math.pi) - context.line_to(x, y) - context.close_path() - (red, green, blue) = self._fill_color - context.set_source_rgb(red, green, blue) - context.fill() - - # Draw circle outline - context.arc(x, y, radius, 0, 2 * math.pi) - context.set_source_rgba(1, 1, 1) - context.set_line_width(1.0) - context.stroke() - -gobject.type_register(PieMeter) - diff --git a/timer-applet/src/timerapplet/ui/PreferencesDialog.py b/timer-applet/src/timerapplet/ui/PreferencesDialog.py deleted file mode 100644 index d42ae911..00000000 --- a/timer-applet/src/timerapplet/ui/PreferencesDialog.py +++ /dev/null @@ -1,192 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gobject -import gtk -import gtk.glade as glade - -class PreferencesDialog(gobject.GObject): - __gsignals__ = \ - { - 'show-remaining-time-changed': - ( - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_BOOLEAN,) - ), - 'play-sound-changed': - ( - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_BOOLEAN,) - ), - 'use-custom-sound-changed': - ( - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_BOOLEAN,) - ), - 'show-popup-notification-changed': - ( - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_BOOLEAN,) - ), - 'show-pulsing-icon-changed': - ( - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_BOOLEAN,) - ), - 'custom-sound-path-changed': - ( - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING,) - ) - } - - __gproperties__ = \ - { - 'show-remaining-time': - (bool, - 'Show remaining time', - 'Whether to show remaining time when the timer is running', - False, - gobject.PARAM_WRITABLE - ), - 'play-sound': - (bool, - 'Play notification sound', - 'Whether to play notification sound when the timer is finished', - False, - gobject.PARAM_WRITABLE - ), - 'use-custom-sound': - (bool, - 'Use custom sound', - 'Whether to use a custom notification sound', - False, - gobject.PARAM_WRITABLE - ), - 'show-popup-notification': - (bool, - 'Show Popup notification', - 'Whether to show a popup notifcation when timer finished', - False, - gobject.PARAM_WRITABLE - ), - 'show-pulsing-icon': - (bool, - 'Show pulsing icon', - 'Whether to show pulsing icon when timer finished', - False, - gobject.PARAM_WRITABLE - ), - 'custom-sound-path': - (str, - 'Custom sound path', - 'Path to a custom notification sound', - '', - gobject.PARAM_WRITABLE - ) - } - - def __init__(self, glade_file_name): - gobject.GObject.__init__(self) - glade_widgets = glade.XML(glade_file_name, 'preferences_dialog') - self._preferences_dialog = glade_widgets.get_widget('preferences_dialog') - self._show_time_check = glade_widgets.get_widget('show_time_check') - self._play_sound_check = glade_widgets.get_widget('play_sound_check') - self._use_default_sound_radio = glade_widgets.get_widget('use_default_sound_radio') - self._use_custom_sound_radio = glade_widgets.get_widget('use_custom_sound_radio') - self._sound_chooser_button = glade_widgets.get_widget('sound_chooser_button') - self._play_sound_box = glade_widgets.get_widget('play_sound_box') - #: Popup notification checkbutton - self._popup_notification_check = glade_widgets.get_widget('popup_notification_check') - #: Pulsing icon checkbutton - self._pulsing_icon_check = glade_widgets.get_widget('pulsing_trayicon_check') - - ####################################################################### - # Signals - ####################################################################### - self._show_time_check.connect('toggled', self._on_show_time_check_toggled) - self._play_sound_check.connect('toggled', self._on_play_sound_check_toggled) - self._use_custom_sound_radio.connect('toggled', self._on_use_custom_sound_radio_toggled) - #: Popup notification checkbutton 'toggled' signal - self._popup_notification_check.connect('toggled', self._on_popup_notification_toggled) - #: Pulsing icon checkbutton 'toggled' signal - self._pulsing_icon_check.connect('toggled', self._on_pulsing_icon_toggled) - - self._sound_chooser_button.connect('selection-changed', self._on_sound_chooser_button_selection_changed) - self._preferences_dialog.connect('delete-event', gtk.Widget.hide_on_delete) - self._preferences_dialog.connect('response', lambda dialog, response_id: self._preferences_dialog.hide()) - - def show(self): - self._preferences_dialog.present() - - def _on_show_time_check_toggled(self, widget): - self.emit('show-remaining-time-changed', widget.props.active) - - def _on_play_sound_check_toggled(self, widget): - self.emit('play-sound-changed', widget.props.active) - - def _on_use_custom_sound_radio_toggled(self, widget): - self.emit('use-custom-sound-changed', widget.props.active) - - def _on_popup_notification_toggled(self, widget): - """Emit a signal when `self._popup_notification_check` gets toggled in - the Preferences dialog window.""" - self.emit('show-popup-notification-changed', widget.props.active) - - def _on_pulsing_icon_toggled(self, widget): - """Emit a signal when `self._popup_notification_check` gets toggled in - the Preferences dialog window.""" - self.emit('show-pulsing-icon-changed', widget.props.active) - - def _on_sound_chooser_button_selection_changed(self, chooser_button): - filename = chooser_button.get_filename() - - # Work around an issue where calling set_filename() will cause - # 3 selection-changed signals to be emitted: first two will have a None filename - # and the third will finally have the desired filename. - if filename is not None: - print 'Custom sound changed to path: %s' % filename - self.emit('custom-sound-path-changed', filename) - - def do_set_property(self, pspec, value): - if pspec.name == 'show-remaining-time': - self._show_time_check.props.active = value - elif pspec.name == 'play-sound': - self._play_sound_check.props.active = value - self._play_sound_box.props.sensitive = value - elif pspec.name == 'use-custom-sound': - if value == True: - self._use_custom_sound_radio.props.active = True - self._sound_chooser_button.props.sensitive = True - else: - # Note: Setting _use_custom_sound_radio.props.active to False - # does not automatically set _use_default_sound_radio.props.active to True - self._use_default_sound_radio.props.active = True - self._sound_chooser_button.props.sensitive = False - elif pspec.name == 'show-popup-notification': - self._popup_notification_check.props.active = value - elif pspec.name == 'show-pulsing-icon': - self._pulsing_icon_check.props.active = value - elif pspec.name == 'custom-sound-path': - # Prevent infinite loop of events. - if self._sound_chooser_button.get_filename() != value: - self._sound_chooser_button.set_filename(value) diff --git a/timer-applet/src/timerapplet/ui/PulseButton.py b/timer-applet/src/timerapplet/ui/PulseButton.py deleted file mode 100644 index 9694ea48..00000000 --- a/timer-applet/src/timerapplet/ui/PulseButton.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import math -import time -import gobject -import gtk - -class PulseButton(gtk.Button): - def __init__(self): - super(PulseButton, self).__init__() - - self._anim_period_seconds = 0.7 - self._start_time = 0.0 - self._factor = 0.0 - - def start_pulsing(self): - self._start_time = time.time() - gobject.timeout_add(10, self._on_timeout) - - def stop_pulsing(self): - self._start_time = 0 - - def _on_timeout(self, data=None): - if self._start_time <= 0.0: - return False - if self.window != None: - delta = time.time() - self._start_time - - if delta > self._anim_period_seconds: - delta = self._anim_period_seconds - self._start_time = time.time() - fraction = delta/self._anim_period_seconds - self._factor = math.sin(fraction * math.pi) - - self.window.invalidate_rect(self.allocation, True) - return True - - def do_expose_event(self, event): - gtk.Button.do_expose_event(self, event) - if self._start_time > 0: - context = event.window.cairo_create() - context.rectangle(0, 0, self.allocation.width, self.allocation.height) - - #color = self.style.bg[gtk.STATE_SELECTED] - #color = gtk.gdk.Color(65535, 65535, 65535) - color = gtk.gdk.Color(0, 0, 0) - red = color.red / 65535.0 - green = color.green / 65535.0 - blue = color.blue / 65535.0 - context.set_source_rgba(red, green, blue, self._factor * 0.8) - context.fill() - - return False - -gobject.type_register(PulseButton) diff --git a/timer-applet/src/timerapplet/ui/ScrollableButtonList.py b/timer-applet/src/timerapplet/ui/ScrollableButtonList.py deleted file mode 100644 index 0af6e51d..00000000 --- a/timer-applet/src/timerapplet/ui/ScrollableButtonList.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gtk - -def get_scroll_value_to_reveal_widget(widget_rect, viewport_rect, scroll_val): - if widget_rect.y < scroll_val: - scroll_val = widget_rect.y - elif widget_rect.y + widget_rect.height + 1 > scroll_val + viewport_rect.height: - scroll_val = widget_rect.y + widget_rect.height + 1 - viewport_rect.height - return scroll_val - -class ScrollableButtonList(gtk.ScrolledWindow): - def __init__(self): - gtk.ScrolledWindow.__init__(self) - - self._vadjust = gtk.Adjustment() - self._vbox = gtk.VBox() - self._viewport = gtk.Viewport() - - self.set_vadjustment(self._vadjust) - self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - self._viewport.modify_bg(gtk.STATE_NORMAL, self.style.base[gtk.STATE_NORMAL]) - - self._viewport.add(self._vbox) - self.add(self._viewport) - - self._vbox.show() - self._viewport.show() - - def add_button(self, button): - button.connect('focus-in-event', self._on_focus) - button.connect('clicked', self._on_clicked) - self._vbox.pack_start(button, False, False) - - def get_buttons(self): - return self._vbox.get_children() - - def _on_focus(self, widget, event): - self._scroll_to_widget(widget) - - def _on_clicked(self, widget): - self._scroll_to_widget(widget) - - def _scroll_to_widget(self, widget): - cur_val = self._vadjust.get_value() - new_val = get_scroll_value_to_reveal_widget(widget.allocation, self._viewport.allocation, cur_val) - - if new_val != cur_val: - self._vadjust.set_value(new_val) - self._vadjust.value_changed() - diff --git a/timer-applet/src/timerapplet/ui/StartNextTimerDialog.py b/timer-applet/src/timerapplet/ui/StartNextTimerDialog.py deleted file mode 100644 index 11886c87..00000000 --- a/timer-applet/src/timerapplet/ui/StartNextTimerDialog.py +++ /dev/null @@ -1,66 +0,0 @@ -# -*- mode: python; coding: utf-8; -*- -# Copyright (C) 2010 Kenny Meyer <[email protected]> -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -""" -The Start Next Timer dialog - -When a timer ended and the auto_start option was disabled this dialog shows up. -""" - -from gettext import gettext as _ -import gtk - -class StartNextTimerDialog(object): - def __init__(self, glade_file_name, header_text, body_text): - # TODO: Include next_timer in body_text - self._dialog = gtk.Dialog( - _("Start Next Timer"), - None, - gtk.DIALOG_DESTROY_WITH_PARENT, - (_("_Don't start next timer"), gtk.RESPONSE_CLOSE, - _("_Start next timer"), gtk.RESPONSE_YES)) - self._dialog.props.border_width = 6 - self._dialog.props.has_separator = False - self._dialog.props.resizable = False - self._dialog.vbox.props.spacing = 12 - self._dialog.set_default_response(gtk.RESPONSE_YES) - - hbox = gtk.HBox(False, 0) - hbox.props.spacing = 12 - hbox.props.border_width = 6 - - image = gtk.image_new_from_stock(gtk.STOCK_DIALOG_QUESTION, gtk.ICON_SIZE_DIALOG) - image.props.yalign = 0.0 - - label = gtk.Label('<span weight="bold" size="larger">%s</span>\n\n%s' % (header_text, body_text)) - label.props.use_markup = True - label.props.wrap = True - label.props.yalign = 0.0 - - hbox.pack_start(image, False, False, 0) - hbox.pack_start(label, False, False, 0) - self._dialog.vbox.pack_start(hbox, False, False, 0) - - hbox.show_all() - - def get_response(self): - dialog_result = self._dialog.run() - self._dialog.hide() - if dialog_result == gtk.RESPONSE_YES: - return True - else: - return False - diff --git a/timer-applet/src/timerapplet/ui/StartTimerDialog.py b/timer-applet/src/timerapplet/ui/StartTimerDialog.py deleted file mode 100644 index 3d0b4f49..00000000 --- a/timer-applet/src/timerapplet/ui/StartTimerDialog.py +++ /dev/null @@ -1,267 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# Copyright (C) 2010 Kenny Meyer <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gobject -import gtk -import gtk.glade as glade -import gtk.gdk as gdk -import pango - -from gettext import gettext as _ -from shlex import split as shell_tokenize -from subprocess import check_call, CalledProcessError - -from DurationChooser import DurationChooser -from ScrollableButtonList import ScrollableButtonList - -class StartTimerDialog(gobject.GObject): - __gsignals__ = {'clicked-start': - (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - 'clicked-cancel': - (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - 'clicked-manage-presets': - (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), - 'clicked-save': - (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, - gobject.TYPE_INT, - gobject.TYPE_INT, - gobject.TYPE_INT, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_BOOLEAN)), - 'clicked-preset': - (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT,)), - 'double-clicked-preset': - (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT,))} - - def __init__(self, glade_file_name, name_validator_func, presets_store, preset_display_func): - gobject.GObject.__init__(self) - - self._valid_name_func = name_validator_func; - self._presets_store = presets_store - self._preset_display_func = preset_display_func - - self._presets_list = ScrollableButtonList() - labels_size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) - self._duration_chooser = DurationChooser(labels_size_group) - - glade_widgets = glade.XML(glade_file_name, 'start_timer_dialog') - self._dialog = glade_widgets.get_widget('start_timer_dialog') - self._ok_button = glade_widgets.get_widget('ok_button') - name_label = glade_widgets.get_widget('name_label') - self._name_entry = glade_widgets.get_widget('name_entry') - self._save_button = glade_widgets.get_widget('save_button') - duration_chooser_container = glade_widgets.get_widget('duration_chooser_container') - presets_chooser_container = glade_widgets.get_widget('presets_chooser_container') - self._presets_section = glade_widgets.get_widget('presets_section') - #: The TextEntry control for running a custom command - self._command_entry = glade_widgets.get_widget('command_entry') - #: The "Invalid Command" label - self._invalid_cmd_label = glade_widgets.get_widget('invalid_command_label') - #: The next timer combo box - self._next_timer_combo = glade_widgets.get_widget('next_timer_combo_entry') - self._next_timer_combo.set_model(self._presets_store) - self._next_timer_combo.set_text_column(0) # The column to be shown - #: The auto-start check button. - self._auto_start_check = glade_widgets.get_widget('auto_start_check') - - labels_size_group.add_widget(name_label) - self._dialog.set_default_response(gtk.RESPONSE_OK) - duration_chooser_container.pack_start(self._duration_chooser) - presets_chooser_container.pack_start(self._presets_list) - - self._dialog.connect('response', self._on_dialog_response) - self._dialog.connect('delete-event', self._dialog.hide_on_delete) - self._dialog.add_events(gdk.BUTTON_PRESS_MASK) - self._duration_chooser.connect('duration-changed', self._on_duration_changed) - self._name_entry.connect('changed', self._on_name_entry_changed) - self._save_button.connect('clicked', self._on_save_button_clicked) - # Check that executable is valid while inserting text - self._command_entry.connect('changed', self._check_is_valid_command) - self._next_timer_combo.child.connect("changed", - self._on_next_timer_combo_entry_child_changed) - glade_widgets.get_widget('manage_presets_button').connect('clicked', - self._on_manage_presets_button_clicked) - self._presets_store.connect('row-deleted', - lambda model, row_path: self._update_presets_list()) - self._presets_store.connect('row-changed', - lambda model, row_path, row_iter: self._update_presets_list()) - - self._update_presets_list() - self._duration_chooser.show() - self._presets_list.show() - - def show(self): - if not self._dialog.props.visible: - self._duration_chooser.clear() - self._duration_chooser.focus_hours() - self._name_entry.set_text('') - self._check_for_valid_start_timer_input() - self._check_for_valid_save_preset_input() - self._dialog.present() - - def hide(self): - self._dialog.hide() - - def get_control_data(self): - """Return name and duration in a tuple. - - The returned tuple is in this format: - - (name, hours, minutes, seconds, next_timer, auto_start) - - """ - return (self._name_entry.get_text().strip(),) + \ - self._duration_chooser.get_duration() + \ - (self._command_entry.get_text().strip(), - self._next_timer_combo.child.get_text().strip(), - self._auto_start_check.get_active()) - - def set_name_and_duration(self, name, hours, minutes, seconds, *args): - self._name_entry.set_text(name) - self._command_entry.set_text(args[0]) - self._next_timer_combo.child.set_text(args[1]) - self._auto_start_check.set_active(args[2]) - self._duration_chooser.set_duration(hours, minutes, seconds) - - def _update_presets_list(self): - self._check_for_valid_save_preset_input() - - if len(self._presets_store) == 0: - self._presets_section.hide() - - # Make window shrink - self._dialog.resize(1, 1) - else: - self._presets_section.show() - - for button in self._presets_list.get_buttons(): - button.destroy() - - row_iter = self._presets_store.get_iter_first() - while row_iter is not None: - name = self._preset_display_func(row_iter) - label = gtk.Label(name) - label.set_ellipsize(pango.ELLIPSIZE_END) - button = gtk.Button() - button.set_relief(gtk.RELIEF_NONE) - button.add(label) - self._presets_list.add_button(button) - - button.connect('clicked', - self._on_preset_button_clicked, - self._presets_store.get_path(row_iter)) - button.connect('button_press_event', - self._on_preset_button_double_clicked, - self._presets_store.get_path(row_iter)) - - label.show() - button.show() - - row_iter = self._presets_store.iter_next(row_iter) - - def _check_is_valid_command(self, widget, data=None): - """ - Check that input in the command entry TextBox control is a valid - executable. - """ - try: - data = widget.get_text() - executable = shell_tokenize(data)[0] - # Check if command in path, else raise CalledProcessError - # The idea of using `which` to check if a command is in PATH - # originated from the Python mailing list. - check_call(['which', executable]) - self._invalid_cmd_label.set_label('') - except (ValueError, IndexError, CalledProcessError): - self._invalid_cmd_label.set_label(_("<b>Command not found.</b>")) - if data is '': - self._invalid_cmd_label.set_label('') - - def _non_zero_duration(self): - (hours, minutes, seconds) = self._duration_chooser.get_duration() - return (hours > 0 or minutes > 0 or seconds > 0) - - def _check_for_valid_save_preset_input(self): - self._save_button.props.sensitive = (self._non_zero_duration() and - self._valid_name_func(self._name_entry.get_text())) - # TODO: Add validator for next_timer_combo - - def _check_for_valid_start_timer_input(self): - self._ok_button.props.sensitive = self._non_zero_duration() - - def _on_preset_button_clicked(self, button, row_path): - self.emit('clicked-preset', row_path) - - def _on_preset_button_double_clicked(self, button, event, row_path): - """Emit the `double-clicked-preset' signal.""" - # Check that the double-click event shot off on the preset button - if event.type == gdk._2BUTTON_PRESS: - self.emit('double-clicked-preset', row_path) - - def _on_manage_presets_button_clicked(self, button): - self.emit('clicked-manage-presets') - - def _on_duration_changed(self, data=None): - self._check_for_valid_start_timer_input() - self._check_for_valid_save_preset_input() - - def _on_name_entry_changed(self, entry): - self._check_for_valid_save_preset_input() - - def _on_dialog_response(self, dialog, response_id): - if response_id == gtk.RESPONSE_OK: - self._duration_chooser.normalize_fields() - self.emit('clicked-start') - elif response_id == gtk.RESPONSE_CANCEL: - self.emit('clicked-cancel') - self._dialog.hide() - - def _on_save_button_clicked(self, button): - self._duration_chooser.normalize_fields() - (hours, minutes, seconds) = self._duration_chooser.get_duration() - name = self._name_entry.get_text() - command = self._command_entry.get_text() - next_timer = self._next_timer_combo.child.get_text() - auto_start = self._auto_start_check.get_active() - self.emit('clicked-save', name, hours, minutes, seconds, command, - next_timer, auto_start) - - def _on_next_timer_combo_entry_child_changed(self, widget, data=None): - """Validate selection of the Next Timer ComboBoxEntry.""" - modelfilter = self._presets_store.filter_new() - # Loop through all rows in ListStore - # TODO: Using a generator may be more memory efficient in this case. - for row in modelfilter: - # Check that name of preset is the exact match of the the text in - # the ComboBoxEntry - if widget.get_text() == row[0]: - # Yes, it matches! Make the auto-start checkbox sensitive - # (activate it). - self._auto_start_check.set_sensitive(True) - break - else: - # If value of ComboBoxEntry is None then de-activate the - # auto-start checkbox. - self._auto_start_check.set_sensitive(False) - diff --git a/timer-applet/src/timerapplet/ui/StatusButton.py b/timer-applet/src/timerapplet/ui/StatusButton.py deleted file mode 100644 index 23e939ce..00000000 --- a/timer-applet/src/timerapplet/ui/StatusButton.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gtk -from PulseButton import PulseButton -from PieMeter import PieMeter - -class StatusButton(PulseButton): - def __init__(self): - PulseButton.__init__(self) - - self._tooltip = gtk.Tooltip() - - self._icon_widget = gtk.Image() - self._pie_meter = PieMeter() - self._label_widget = gtk.Label() - self._visual_box = gtk.HBox() - - self._visual_box.pack_start(self._icon_widget) - self._visual_box.pack_start(self._pie_meter) - - self._layout_box = None - self._use_vertical = None - self.set_use_vertical_layout(False) - - # _pie_meter will default to visible while - # _icon_widget will default to hidden. - self._pie_meter.show() - self._visual_box.show() - self._label_widget.show() - - def set_tooltip(self, tip_text): - self._tooltip.set_text(tip_text) - - def set_label(self, text): - self._label_widget.set_text(text) - - def set_icon(self, image_path): - self._icon_widget.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(image_path, -1, 20)) - #elf._icon_widget.set_from_file(image_path) - - def set_use_icon(self, use_icon): - if use_icon: - self._pie_meter.hide() - self._icon_widget.show() - else: - self._pie_meter.show() - self._icon_widget.hide() - - def set_sensitized(self, sensitized): - self._label_widget.props.sensitive = sensitized - - def set_show_remaining_time(self, show_remaining_time): - if show_remaining_time: - self._label_widget.show() - else: - self._label_widget.hide() - - def set_progress(self, progress): - self._pie_meter.set_progress(progress) - - def set_use_vertical_layout(self, use_vertical): - if self._use_vertical == use_vertical: - return - - self._use_vertical = use_vertical - if self._layout_box is not None: - self._layout_box.remove(self._visual_box) - self._layout_box.remove(self._label_widget) - self.remove(self._layout_box) - self._layout_box.destroy() - self._layout_box = None - - new_layout_box = None - if self._use_vertical: - new_layout_box = gtk.VBox(False, 2) - else: - new_layout_box = gtk.HBox(False, 2) - - new_layout_box.pack_start(self._visual_box, True, True, 0) - new_layout_box.pack_start(self._label_widget, False, False, 0) - - self._layout_box = new_layout_box - self.add(self._layout_box) - self._layout_box.show() - - def set_pie_fill_color(self, red, green, blue): - self._pie_meter.set_fill_color(red, green, blue) diff --git a/timer-applet/src/timerapplet/ui/__init__.py b/timer-applet/src/timerapplet/ui/__init__.py deleted file mode 100644 index a0da1fa4..00000000 --- a/timer-applet/src/timerapplet/ui/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from AddEditPresetDialog import AddEditPresetDialog -from ContinueTimerDialog import ContinueTimerDialog -from DurationChooser import DurationChooser -from ManagePresetsDialog import ManagePresetsDialog -from Notifier import Notifier -from PieMeter import PieMeter -from PreferencesDialog import PreferencesDialog -from PulseButton import PulseButton -from ScrollableButtonList import ScrollableButtonList -from StartTimerDialog import StartTimerDialog -from StartNextTimerDialog import StartNextTimerDialog -from StatusButton import StatusButton diff --git a/timer-applet/src/timerapplet/utils.py b/timer-applet/src/timerapplet/utils.py deleted file mode 100644 index 02113501..00000000 --- a/timer-applet/src/timerapplet/utils.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) 2008 Jimmy Do <[email protected]> -# Copyright (C) 2010 Kenny Meyer <[email protected]> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -from gettext import gettext as _ - -def is_valid_preset_name(name_str, preset_store, allowed_names=()): - if len(name_str) == 0: - return False - - name_str = name_str.lower() - for allowed in allowed_names: - if name_str == allowed.lower(): - return True - - return not preset_store.preset_name_exists_case_insensitive(name_str) - -def seconds_to_hms(total_seconds): - (hours, remaining_seconds) = divmod(total_seconds, 3600) - (minutes, seconds) = divmod(remaining_seconds, 60) - return (hours, minutes, seconds) - -def hms_to_seconds(hours, minutes, seconds): - return hours * 3600 + minutes * 60 + seconds - -def construct_time_str(remaining_seconds, show_all=True): - """Return a user-friendly representation of remaining time based on the given number of seconds. - - show_all specifies whether the returned string should show all time components. - If show_all is True (default), the returned string is in HH:MM:SS format. - If show_all is False, the returned string is in either HH:MM or MM:SS format, - depending on how much time is remaining. This avoids showing the user more - information than necessary. - - """ - hours, minutes, seconds = seconds_to_hms(remaining_seconds) - if show_all: - # HH:MM:SS - return _('%02d:%02d:%02d') % (hours, minutes, seconds) - else: - if hours > 0 or minutes > 14: - # HH:MM - return _('%02d:%02d') % (hours, minutes) - else: - # MM:SS - return _('%02d:%02d') % (minutes, seconds) - -def get_display_text_from_datetime(date_time): - return date_time.strftime('%X') - -def get_preset_display_text(presets_store, row_iter): - (name, hours, minutes, seconds, command, next_timer, auto_start) = \ - presets_store.get_preset(row_iter) - - # <preset name> (HH:MM:SS) - return _('%s (%02d:%02d:%02d)') % (name, hours, minutes, seconds) - -def serialize_bool(boolean): - if boolean: - return "1" - return "0" - -def deserialize_bool(string): - if string == "1": - return True - return False |