~ubuntu-branches/ubuntu/lucid/awn-extras-applets/lucid

« back to all changes in this revision

Viewing changes to applets/maintained/digital-clock/dgClockPref.py

  • Committer: Bazaar Package Importer
  • Author(s): Julien Lavergne
  • Date: 2010-03-30 20:26:40 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100330202640-vza3bdnv9gc9bg5z
Tags: 0.4.0~rc1-0ubuntu1
* New upstream release (rc1) (LP: #551309)
 - Stack applet close on click (LP: #261520)
* debian/patches/
 - 03-remove-cairo-menu-pref.patch: From upstream (r1244 + r1245 + r1252),
   remove menu entry for cairo-menu preferences, it's not implemented
   (LP: #511254)
 - 04-tomboy-threading-free.patch: From upstream (r1246), remove threading to
   make the applet working. 
* debian/*.install: Update installation location of comics and digital 
  applets.
* debian/control: 
 - Move digital applet from python to C, and add proper Replaces.
 - Add Replaces for awn-applets-c-core to handle migration from 0.3.2.2.
   (LP: #524559)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# encoding: utf-8
2
 
#
3
 
# Copyright Ryan Rushton  ryan@rrdesign.ca
4
 
# This program is free software; you can redistribute it and/or modify
5
 
# it under the terms of the GNU General Public License as published by
6
 
# the Free Software Foundation; either version 2 of the License, or
7
 
# (at your option) any later version.
8
 
#
9
 
# This program is distributed in the hope that it will be useful,
10
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
# GNU Library General Public License for more details.
13
 
#
14
 
# You should have received a copy of the GNU General Public License
15
 
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
17
 
 
18
 
import re
19
 
import subprocess
20
 
import time
21
 
 
22
 
import gobject
23
 
from desktopagnostic import Color, config
24
 
from desktopagnostic.ui import ColorButton
25
 
import gtk
26
 
import awn
27
 
from awn import extras
28
 
from awn.extras import _
29
 
 
30
 
 
31
 
class ClockPrefs(gobject.GObject):
32
 
 
33
 
    # not using gobject.property because of
34
 
    # http://bugzilla.gnome.org/show_bug.cgi?id=593241
35
 
    __gproperties__ = {
36
 
        'date_before_time': (bool, _('Date before time'),
37
 
                             _('Whether to show the date next to the time, instead of below it.'),
38
 
                             False,
39
 
                             gobject.PARAM_READWRITE),
40
 
        'twelve_hour': (bool, _('12 hour mode'),
41
 
                        _('Whether to show the time in 12 hour mode (as opposed to 24 hour mode).'),
42
 
                        False,
43
 
                        gobject.PARAM_READWRITE),
44
 
        'font_face': (str, _('Font face'),
45
 
                      _('The font face for the date and time text.'),
46
 
                      'Sans 10',
47
 
                      gobject.PARAM_READWRITE),
48
 
        'font_color': (Color, _('Font color'),
49
 
                       _('The text color of the date and time.'),
50
 
                       gobject.PARAM_READWRITE),
51
 
        'font_shadow_color': (Color, _('Font shadow color'),
52
 
                              _('The font shadow color of the date and time.'),
53
 
                              gobject.PARAM_READWRITE),
54
 
        'calendar_command': (str, _('Calendar command'),
55
 
                             _('Command to execute when a calendar day is double-clicked.'),
56
 
                             '', gobject.PARAM_READWRITE),
57
 
        'adjust_datetime_command': (str, _('Adjust date/time command'),
58
 
                                    _('Command to execute when the user wishes to adjust the date/time.'),
59
 
                                    '', gobject.PARAM_READWRITE),
60
 
        'orientation': (gtk.Orientation, _('dock orientation'),
61
 
                        _('The orientation of the dock (horizontal/vertical)'),
62
 
                        gtk.ORIENTATION_HORIZONTAL,
63
 
                        gobject.PARAM_READWRITE)}
64
 
 
65
 
    __alpha = {
66
 
        'font_color': 0,
67
 
        'font_shadow_color': 0xcccc
68
 
        }
69
 
 
70
 
    pref_map = {
71
 
      'dbt': 'date-before-time',
72
 
      'hour12': 'twelve-hour',
73
 
      'font_face': 'font-face',
74
 
      'font_color': 'font-color',
75
 
      'font_shadow_color': 'font-shadow-color'}
76
 
 
77
 
    cmd_pref_map = {
78
 
        'calendar': 'calendar_command',
79
 
        'adjust_datetime': 'adjust_datetime_command'
80
 
        }
81
 
 
82
 
    def do_get_property(self, param):
83
 
        attr = '__%s' % param.name.replace('-', '_')
84
 
        return getattr(self, attr, None)
85
 
 
86
 
    def do_set_property(self, param, value):
87
 
        attr = '__%s' % param.name.replace('-', '_')
88
 
        setattr(self, attr, value)
89
 
 
90
 
    def __init__(self, applet):
91
 
        super(ClockPrefs, self).__init__()
92
 
        self.applet = applet
93
 
        self.config = awn.config_get_default_for_applet(self.applet)
94
 
        for key, prop in self.pref_map.iteritems():
95
 
            self.config.bind(config.GROUP_DEFAULT, key,
96
 
                             self, prop, False, config.BIND_METHOD_FALLBACK)
97
 
        for key, prop in self.cmd_pref_map.iteritems():
98
 
            self.config.bind('commands', key, self, prop, False,
99
 
                             config.BIND_METHOD_FALLBACK)
100
 
        self.on_applet_pos_changed(self.applet, self.applet.props.position)
101
 
        self.applet.connect('position-changed', self.on_applet_pos_changed)
102
 
        self.menu = self.build_menu()
103
 
        self.window = None
104
 
 
105
 
    def on_applet_pos_changed(self, applet, pos):
106
 
        if pos in (gtk.POS_TOP, gtk.POS_BOTTOM):
107
 
           self.props.orientation = gtk.ORIENTATION_HORIZONTAL
108
 
        else:
109
 
           self.props.orientation = gtk.ORIENTATION_VERTICAL
110
 
 
111
 
    def date_before_time_enabled(self):
112
 
        return self.props.date_before_time and \
113
 
               self.props.orientation == gtk.ORIENTATION_HORIZONTAL
114
 
 
115
 
    def build_image_menu_item(self, menu, icon_name, activate_callback, label=None):
116
 
        if label is None:
117
 
            item = gtk.ImageMenuItem(icon_name)
118
 
        else:
119
 
            item = awn.image_menu_item_new_with_label(label)
120
 
            item.set_image(gtk.image_new_from_stock(icon_name, gtk.ICON_SIZE_MENU))
121
 
        item.connect('activate', activate_callback)
122
 
        menu.append(item)
123
 
 
124
 
    def build_menu(self):
125
 
        popup_menu = self.applet.create_default_menu()
126
 
 
127
 
        self.build_image_menu_item(popup_menu, gtk.STOCK_COPY,
128
 
                                   self.copy_time,
129
 
                                   _('Copy Time'))
130
 
        self.build_image_menu_item(popup_menu, gtk.STOCK_COPY,
131
 
                                   self.copy_date,
132
 
                                   _('Copy Date'))
133
 
        self.build_image_menu_item(popup_menu, gtk.STOCK_PREFERENCES,
134
 
                                   self.show_prefs)
135
 
        self.build_image_menu_item(popup_menu, gtk.STOCK_EDIT,
136
 
                                   self.time_admin,
137
 
                                   _('Adjust Date & Time'))
138
 
        about_item = self.applet.create_about_item('Copyright © 2007 Ryan Rushton',
139
 
                                                   awn.APPLET_LICENSE_GPLV2,
140
 
                                                   extras.__version__, None,
141
 
                                                   'http://wiki.awn-project.org/Digital_Clock',
142
 
                                                   _('Wiki'),
143
 
                                                   'awn-applet-digital-clock',
144
 
                                                   None, ['Ryan Rushton', 'Mark Lee'],
145
 
                                                   None, None)
146
 
        popup_menu.append(about_item)
147
 
 
148
 
        popup_menu.show_all()
149
 
        return popup_menu
150
 
 
151
 
    def show_prefs(self, widget):
152
 
        if self.window is None:
153
 
            self.window = PrefsDialog(self)
154
 
        self.window.show_all()
155
 
 
156
 
    def copy_date(self, widget):
157
 
        cb = gtk.Clipboard()
158
 
        txt = time.strftime('%A, %B %d, %Y')
159
 
        cb.set_text(txt)
160
 
 
161
 
    def copy_time(self, widget):
162
 
        cb = gtk.Clipboard()
163
 
        if self.props.twelve_hour:
164
 
            h = time.strftime('%I').lstrip('0')
165
 
            txt = h + time.strftime(':%M:%S %p')
166
 
        else:
167
 
            txt = time.strftime('%H:%M:%S')
168
 
        cb.set_text(txt)
169
 
 
170
 
    def time_admin(self, widget):
171
 
        subprocess.Popen(self.props.adjust_datetime_command, shell=True)
172
 
 
173
 
 
174
 
class HRadioGroup(gtk.Frame):
175
 
 
176
 
    def __init__(self, label=None):
177
 
        super(HRadioGroup, self).__init__(label)
178
 
        self.hbox = gtk.HBox(5, False)
179
 
        super(HRadioGroup, self).add(self.hbox)
180
 
        self.buttons = []
181
 
        self.connect('notify::sensitive', self.on_sensitive_changed)
182
 
 
183
 
    def add_radio(self, label=None, use_underline=True, signals={},
184
 
                  active=None):
185
 
        group = None
186
 
        if len(self.buttons) > 0:
187
 
            group = self.buttons[0]
188
 
        radio = gtk.RadioButton(group=group, label=label, use_underline=use_underline)
189
 
        for signal, args in signals.iteritems():
190
 
            radio.connect(signal, *args)
191
 
        self.hbox.add(radio)
192
 
        self.buttons.append(radio)
193
 
        return radio
194
 
 
195
 
    def on_sensitive_changed(self, pspec):
196
 
        for button in self.buttons:
197
 
            button.props.sensitive = self.props.sensitive
198
 
 
199
 
 
200
 
class CommandSelector:
201
 
    def __init__(self, label, prefs, options, property_name):
202
 
        model = gtk.ListStore(str, str)
203
 
        self.prefs = prefs
204
 
        self.prop = property_name
205
 
        self.dropdown = gtk.ComboBox(model)
206
 
        cell = gtk.CellRendererText()
207
 
        self.dropdown.pack_start(cell, True)
208
 
        self.dropdown.add_attribute(cell, 'text', 0)
209
 
        self.options = options
210
 
        self.option_map = {}
211
 
        value = getattr(prefs.props, self.prop)
212
 
        active_set = False
213
 
        idx = 0
214
 
        for option in options:
215
 
            model.append(option)
216
 
            self.option_map[option[1]] = idx
217
 
            if option[1] == value:
218
 
                self.dropdown.props.active = idx
219
 
                active_set = True
220
 
            idx += 1
221
 
        model.append([_('Custom'), None])
222
 
        self.custom = gtk.Entry()
223
 
        self.custom.props.sensitive = not active_set
224
 
        if not active_set:
225
 
            self.dropdown.props.active = len(self.options)
226
 
            self.custom.props.text = value
227
 
        self.label = mnemonic_label(label, self.dropdown)
228
 
        prefs.connect('notify::%s' % self.prop, self.on_prop_changed)
229
 
        self.dropdown.connect('changed', self.on_dropdown_changed)
230
 
        self.custom.connect('changed', self.on_custom_changed)
231
 
 
232
 
    def on_prop_changed(self, obj, pspec):
233
 
        value = getattr(self.prefs.props, self.prop)
234
 
        self.dropdown.active = self.option_map.get(value, len(self.options))
235
 
 
236
 
    def on_dropdown_changed(self, dropdown):
237
 
        idx = dropdown.props.active
238
 
        self.custom.props.sensitive = (idx == len(self.options))
239
 
        if self.custom.props.sensitive:
240
 
            if self.custom.props.text == '':
241
 
                self.custom.props.text = getattr(self.prefs.props, self.prop)
242
 
            self.custom.select_region(0, len(self.custom.props.text))
243
 
        else:
244
 
            active_iter = self.dropdown.get_active_iter()
245
 
            value = self.dropdown.props.model.get_value(active_iter, 1)
246
 
            setattr(self.prefs.props, self.prop, value)
247
 
 
248
 
    def on_custom_changed(self, entry):
249
 
        setattr(self.prefs.props, self.prop, entry.props.text)
250
 
 
251
 
    def attach_to_table(self, table, row):
252
 
        table.attach(self.label, 0, 1, row, row + 1, yoptions=gtk.SHRINK)
253
 
        table.attach(self.dropdown, 1, 2, row, row + 1, yoptions=gtk.SHRINK)
254
 
        table.attach(self.custom, 1, 2, row + 1, row + 2, yoptions=gtk.SHRINK)
255
 
 
256
 
 
257
 
def mnemonic_label(mnemonic, widget):
258
 
    label = gtk.Label()
259
 
    label.set_text_with_mnemonic(mnemonic)
260
 
    label.set_mnemonic_widget(widget)
261
 
    return label
262
 
 
263
 
 
264
 
class PrefsDialog(gtk.Dialog):
265
 
    def __init__(self, prefs):
266
 
        title = _('%s Preferences') % prefs.applet.props.display_name
267
 
        super(PrefsDialog, self).__init__(title, prefs.applet)
268
 
        self.props.icon_name = 'gtk-preferences'
269
 
        self.prefs = prefs
270
 
        self.font_replace = None
271
 
        self.create_ui()
272
 
        # action button
273
 
        self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
274
 
        self.connect('response', lambda dialog, response: dialog.hide())
275
 
        self.prefs.connect('notify::orientation', self.on_orient_changed)
276
 
 
277
 
    def create_ui(self):
278
 
        notebook = gtk.Notebook()
279
 
        # appearance
280
 
        table = gtk.Table(5, 2)
281
 
        table.props.row_spacing = 5
282
 
        table.props.column_spacing = 5
283
 
        # * font face
284
 
        text_font_button = gtk.FontButton(self.prefs.props.font_face)
285
 
        text_font_button.connect('font-set', self.font_changed, 'font_face')
286
 
        text_font_label = mnemonic_label('Font _Face:', text_font_button)
287
 
        table.attach(text_font_label, 0, 1, 0, 1)
288
 
        table.attach(text_font_button, 1, 2, 0, 1)
289
 
        # * font color
290
 
        text_color_button = ColorButton.with_color(self.prefs.props.font_color)
291
 
        text_color_button.connect('color-set', self.color_changed,
292
 
                                  'font_color')
293
 
        text_color_label = mnemonic_label(_('Font _Color:'), text_color_button)
294
 
        table.attach(text_color_label, 0, 1, 1, 2)
295
 
        table.attach(text_color_button, 1, 2, 1, 2)
296
 
        # * font shadow color
297
 
        text_shadow_color_button = \
298
 
                ColorButton.with_color(self.prefs.props.font_shadow_color)
299
 
        text_shadow_color_button.connect('color-set', self.color_changed,
300
 
                                         'font_shadow_color')
301
 
        text_shadow_color_label = mnemonic_label(_('Font _Shadow Color:'),
302
 
                                                 text_color_button)
303
 
        table.attach(text_shadow_color_label, 0, 1, 2, 3)
304
 
        table.attach(text_shadow_color_button, 1, 2, 2, 3)
305
 
        # * clock type: 12/24 hour
306
 
        clock_type = HRadioGroup(_('Clock Type'))
307
 
        clock_type.add_radio(_('_12 Hour'),
308
 
                signals={'toggled': (self.radiobutton_changed,
309
 
                                     'twelve_hour')})
310
 
        clock_type.add_radio(_('_24 Hour'),
311
 
                active=not self.prefs.props.twelve_hour)
312
 
        table.attach(clock_type, 0, 2, 3, 4)
313
 
        # * clock style: time beside date
314
 
        self.clock_style = HRadioGroup(_('Date Position'))
315
 
        self.clock_style.add_radio(_('_Left'),
316
 
               signals={'toggled': (self.radiobutton_changed,
317
 
                                    'date_before_time')})
318
 
        self.clock_style.add_radio(_('_Bottom'),
319
 
               active=not self.prefs.props.date_before_time)
320
 
        self.set_clock_style_sensitivity()
321
 
        table.attach(self.clock_style, 0, 2, 4, 5)
322
 
        appearance_label = mnemonic_label(_('_Appearance'), table)
323
 
        notebook.append_page(table, appearance_label)
324
 
        # commands
325
 
        cmd_table = gtk.Table(4, 2)
326
 
        cmd_table.props.row_spacing = 5
327
 
        cmd_table.props.column_spacing = 5
328
 
        cmd_label = mnemonic_label(_('C_ommands'), cmd_table)
329
 
        # * calendar
330
 
        cal_options = [[_('Evolution (default)'), 'evolution calendar:///?startdate=%02(year)d%02(month)d%02(day)dT120000']]
331
 
        calendar_cmd = CommandSelector(_('Run Cal_endar:'), self.prefs,
332
 
                                       cal_options, 'calendar-command')
333
 
        calendar_cmd.attach_to_table(cmd_table, 0)
334
 
        # * time admin
335
 
        time_options = [[_('GNOME System Tools (default)'), 'gksudo time-admin']]
336
 
        time_cmd = CommandSelector(_('Run _Time Admin:'), self.prefs,
337
 
                                   time_options, 'adjust-datetime-command')
338
 
        time_cmd.attach_to_table(cmd_table, 2)
339
 
        notebook.append_page(cmd_table, cmd_label)
340
 
        self.vbox.add(notebook)
341
 
 
342
 
    def radiobutton_changed(self, check, prop):
343
 
        setattr(self.prefs.props, prop, check.get_active())
344
 
 
345
 
    def font_changed(self, font_btn, prop):
346
 
        font = self.clean_font_name(font_btn.get_font_name())
347
 
        setattr(self.prefs.props, prop, font)
348
 
 
349
 
    def clean_font_name(self, font_face):
350
 
        if self.font_replace is None:
351
 
            attrs = ['Condensed', 'Book', 'Oblique', 'Bold', 'Italic',
352
 
                     'Regular', 'Medium', 'Light']
353
 
            self.font_replace = re.compile('(?:%s ?)*[\d ]*$' % '|'.join(attrs))
354
 
        return self.font_replace.sub('', font_face)
355
 
 
356
 
    def color_changed(self, color_btn, prop):
357
 
        setattr(self.prefs.props, prop, color_btn.props.da_color)
358
 
 
359
 
    def on_orient_changed(self, prefs, pspec):
360
 
        self.set_clock_style_sensitivity()
361
 
 
362
 
    def set_clock_style_sensitivity(self):
363
 
        self.clock_style.props.sensitive = \
364
 
                (self.prefs.props.orientation == gtk.ORIENTATION_HORIZONTAL)
365
 
 
366
 
# vim: set ts=4 sts=4 sw=4 et ai cindent :