class Scene(quickstart.scenes.BaseScene): """ Desktop preferences. """ events = { "toggled": ("show_all", "savespace_enable"), "cursor-changed": ("locale_view",), } @quickstart.threads.thread def set_locale(self, locale, sel, itr): """ Sets the given locale. """ try: self.Locale.set(locale) self.default = itr # Create stamp self.Locale.create_stamp([".alan2-locale-changed"]) GObject.idle_add(self.RebootDialog.show) except: sel.select_iter(self.default) GObject.idle_add(self.objects.region_spinner.hide) GObject.idle_add(self.scene_container.set_sensitive, True) @quickstart.threads.thread def savespace_purge(self, locale): """ Purges foreign locales. """ self.Locale.savespace_purge(locale) GObject.idle_add(self.objects.other_spinner.hide) GObject.idle_add(self.scene_container.set_sensitive, True) def on_locale_view_cursor_changed(self, locale_view): """ Fired when the user changes the locale. """ # selection sel = self.objects.locale_view.get_selection() if not sel: return # iter model, itr = sel.get_selected() if not itr: return selected = self.objects.locales.get_value(itr, 0) if selected == self.Locale.default: return if self.objects.savespace_enable.get_active(): # Display warning if self.objects.savespace_warning.run() == Gtk.ResponseType.NO: self.objects.savespace_warning.hide() sel.select_iter(self.default) return self.objects.savespace_enable.set_active(False) self.objects.savespace_warning.hide() GObject.idle_add(self.objects.region_spinner.show) GObject.idle_add(self.scene_container.set_sensitive, False) self.set_locale(selected, sel, itr) def on_show_all_toggled(self, checkbutton): """ Fired when the 'Show all locales' checkbutton has been clicked. """ GObject.idle_add(self.build_locale_list, self.objects.show_all.get_active()) def on_savespace_enable_toggled(self, checkbutton): """ Fired when the 'Enable savespace' checkbutton has been clicked. """ locale = self.objects.locales.get_value(self.default, 0) if checkbutton.get_active(): self.Locale.savespace_enable(locale) # Purge window if self.objects.savespace_window.run() == Gtk.ResponseType.YES: # Purge!! self.savespace_purge(locale) GObject.idle_add(self.objects.other_spinner.show) GObject.idle_add(self.scene_container.set_sensitive, False) self.objects.savespace_window.hide() else: self.Locale.savespace_disable() def build_locale_list(self, all=False): """ Populates the listbox with locales. """ self.objects.locales.clear() for locale, human in self.Locale.human_form(all=all).items(): if all: codepage = self.Locale.codepages[locale] else: codepage = "" itr = self.objects.locales.append((locale, human, codepage)) # Save iter if this is the default... if locale == self.Locale.default: self.default = itr if self.default: sel = self.objects.locale_view.get_selection() sel.select_iter(self.default) GObject.idle_add(self.objects.locale_view.scroll_to_cell, sel.get_selected_rows()[1][0]) def on_locked(self, unlockbar): """ Fired when the scene has been locked. """ GObject.idle_add(self.objects.content.set_sensitive, False) def on_unlocked(self, unlockbar): """ Fired when the scene has been unlocked. """ GObject.idle_add(self.objects.content.set_sensitive, True) def prepare_scene(self): """ Called when doing the scene setup. """ self.scene_container = self.objects.main # Check for savespace... if os.path.exists("/etc/dpkg/dpkg.cfg.d/keeptalking"): self.objects.savespace_enable.set_active(True) # Create unlockbar self.unlockbar = UnlockBar("org.semplicelinux.keeptalking2.change-locale") self.unlockbar.connect("locked", self.on_locked) self.unlockbar.connect("unlocked", self.on_unlocked) self.objects.main.pack_start(self.unlockbar, False, False, 0) self.Locale = Locale() self.default = None # Make the locale_view treeview working... locale_renderer = Gtk.CellRendererText() self.locale_column = Gtk.TreeViewColumn("Locale", locale_renderer, text=1) self.objects.locales.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.objects.locale_view.append_column(self.locale_column) type_renderer = Gtk.CellRendererText() self.type_column = Gtk.TreeViewColumn("Type", type_renderer, text=2) self.objects.locale_view.append_column(self.type_column) # Populate the locale list GObject.idle_add(self.build_locale_list) def on_scene_called(self): """ Show the scene! """ # We are locked self.unlockbar.emit("locked") self.cancellable = Gio.Cancellable() self.RebootDialog = RebootDialog(self.cancellable) self.RebootDialog.bind_property( "visible", self.scene_container, "sensitive", GObject.BindingFlags.INVERT_BOOLEAN ) def on_scene_asked_to_close(self): """ Do some cleanup before returning home """ self.unlockbar.cancel_authorization() self.cancellable.cancel() return True
class Scene(quickstart.scenes.BaseScene): """ Keyboard settings. """ events = { "changed": ("model_combo", ), "cursor-changed": ("layout_view", "variant_view"), } def setxkbmap(self): """ Invokes setxkbmap and sets the currently selected layout, variant and model. """ subprocess.call([ "setxkbmap", self.Keyboard.default_layout, self.Keyboard.default_variant if self.Keyboard.default_variant else "", "-model" if self.Keyboard.default_model else "", self.Keyboard.default_model if self.Keyboard.default_model else "" ]) def on_model_combo_changed(self, combobox): """ Fired when the user changes the keyboard model. """ itr = self.objects.model_combo.get_active_iter() if not itr: return selected = self.objects.models.get_value(itr, 0) if selected == self.Keyboard.default_variant: return try: self.Keyboard.set(model=selected) self.default_model = itr self.setxkbmap() except: self.objects.model_combo.set_active_iter(self.default_model) def on_variant_view_cursor_changed(self, treeview): """ Fired when the user changes the variant. """ if self.building_list: return # selection sel = treeview.get_selection() if not sel: return # iter model, itr = sel.get_selected() if not itr: return selected = self.objects.variants.get_value(itr, 0) if selected == self.Keyboard.default_variant: return try: self.Keyboard.set(variant=selected) self.default_variant = itr self.setxkbmap() except: sel.select_iter(self.default_variant) def on_layout_view_cursor_changed(self, treeview): """ Fired when the user changes the locale. """ # selection sel = treeview.get_selection() if not sel: return # iter model, itr = sel.get_selected() if not itr: return selected = self.objects.layouts.get_value(itr, 0) if selected == self.Keyboard.default_layout: return # Reset default variant self.default_variant = None try: self.Keyboard.set(layout=selected, variant='') self.default = itr self.setxkbmap() except: sel.select_iter(self.default) # Rebuild variant list GObject.idle_add(self.build_variant_list, selected) def build_variant_list(self, layout): """ Populates the variant list. """ self.building_list = True self.objects.variants.clear() models, layouts = self.Keyboard.supported() variants = layouts[layout]["variants"] for variant in variants: for item, key in variant.items(): itr = self.objects.variants.append([item, key]) # Save the default variant if item == self.Keyboard.default_variant: self.default_variant = itr # No variant reciter = self.objects.variants.prepend( ['', layouts[layout]["description"]]) sel = self.objects.variant_view.get_selection() if self.default_variant: sel.select_iter(self.default) else: # No variant, use reciter sel.select_iter(reciter) GObject.idle_add(self.objects.variant_view.scroll_to_cell, sel.get_selected_rows()[1][0]) self.building_list = False def build_model_list(self): """ Populates the model list. """ pc105 = None self.objects.models.clear() models = self.Keyboard.supported()[0] for item, key in models.items(): itr = self.objects.models.append([item, key]) # Save the default model if item == self.Keyboard.default_model: self.default_model = itr elif item == "pc105": # Fallback pc105 = itr if self.default_model: self.objects.model_combo.set_active_iter(self.default_model) else: self.objects.model_combo.set_active_iter(pc105) def build_layout_list(self): """ Populates the layout list. """ self.objects.layouts.clear() models, layouts = self.Keyboard.supported() for item, key in layouts.items(): itr = self.objects.layouts.append([item, key["description"]]) # Save iter if it's the default... if item == self.Keyboard.default_layout: self.default = itr if self.default: sel = self.objects.layout_view.get_selection() sel.select_iter(self.default) GObject.idle_add(self.objects.layout_view.scroll_to_cell, sel.get_selected_rows()[1][0]) # Also build the variant view! GObject.idle_add(self.build_variant_list, self.Keyboard.default_layout) def on_locked(self, unlockbar): """ Fired when the scene has been locked. """ GObject.idle_add(self.objects.content.set_sensitive, False) def on_unlocked(self, unlockbar): """ Fired when the scene has been unlocked. """ GObject.idle_add(self.objects.content.set_sensitive, True) def prepare_scene(self): """ Called when doing the scene setup. """ self.scene_container = self.objects.main # Create unlockbar self.unlockbar = UnlockBar("org.freedesktop.locale1.set-keyboard") self.unlockbar.connect("locked", self.on_locked) self.unlockbar.connect("unlocked", self.on_unlocked) self.objects.main.pack_start(self.unlockbar, False, False, 0) self.Keyboard = Keyboard() self.building_list = False self.default = None self.default_variant = None self.default_model = None # Make the layout_view treeview working... layout_renderer = Gtk.CellRendererText() self.layout_column = Gtk.TreeViewColumn("Layout", layout_renderer, text=1) self.objects.layouts.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.objects.layout_view.append_column(self.layout_column) # Do the same for the variant_view... variant_renderer = Gtk.CellRendererText() self.variant_column = Gtk.TreeViewColumn("Variant", variant_renderer, text=1) self.objects.variants.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.objects.variant_view.append_column(self.variant_column) # And something similar for the model combobox... model_renderer = Gtk.CellRendererText() self.objects.model_combo.pack_start(model_renderer, True) self.objects.model_combo.add_attribute(model_renderer, "text", 1) self.objects.models.set_sort_column_id(1, Gtk.SortType.ASCENDING) # Populate the layout list GObject.idle_add(self.build_layout_list) # Populate the model list GObject.idle_add(self.build_model_list) def on_scene_called(self): """ Show the scene! """ # We are locked self.unlockbar.emit("locked") def on_scene_asked_to_close(self): """ Do some cleanup before returning home """ self.unlockbar.cancel_authorization() return True
class Scene(quickstart.scenes.BaseScene): """ Desktop preferences. """ events = { "toggled": ("show_all", "savespace_enable"), "cursor-changed": ("locale_view", ), } @quickstart.threads.thread def set_locale(self, locale, sel, itr): """ Sets the given locale. """ try: self.Locale.set(locale) self.default = itr # Create stamp self.Locale.create_stamp([".alan2-locale-changed"]) GObject.idle_add(self.RebootDialog.show) except: sel.select_iter(self.default) GObject.idle_add(self.objects.region_spinner.hide) GObject.idle_add(self.scene_container.set_sensitive, True) @quickstart.threads.thread def savespace_purge(self, locale): """ Purges foreign locales. """ self.Locale.savespace_purge(locale) GObject.idle_add(self.objects.other_spinner.hide) GObject.idle_add(self.scene_container.set_sensitive, True) def on_locale_view_cursor_changed(self, locale_view): """ Fired when the user changes the locale. """ # selection sel = self.objects.locale_view.get_selection() if not sel: return # iter model, itr = sel.get_selected() if not itr: return selected = self.objects.locales.get_value(itr, 0) if selected == self.Locale.default: return if self.objects.savespace_enable.get_active(): # Display warning if self.objects.savespace_warning.run() == Gtk.ResponseType.NO: self.objects.savespace_warning.hide() sel.select_iter(self.default) return self.objects.savespace_enable.set_active(False) self.objects.savespace_warning.hide() GObject.idle_add(self.objects.region_spinner.show) GObject.idle_add(self.scene_container.set_sensitive, False) self.set_locale(selected, sel, itr) def on_show_all_toggled(self, checkbutton): """ Fired when the 'Show all locales' checkbutton has been clicked. """ GObject.idle_add(self.build_locale_list, self.objects.show_all.get_active()) def on_savespace_enable_toggled(self, checkbutton): """ Fired when the 'Enable savespace' checkbutton has been clicked. """ locale = self.objects.locales.get_value(self.default, 0) if checkbutton.get_active(): self.Locale.savespace_enable(locale) # Purge window if self.objects.savespace_window.run() == Gtk.ResponseType.YES: # Purge!! self.savespace_purge(locale) GObject.idle_add(self.objects.other_spinner.show) GObject.idle_add(self.scene_container.set_sensitive, False) self.objects.savespace_window.hide() else: self.Locale.savespace_disable() def build_locale_list(self, all=False): """ Populates the listbox with locales. """ self.objects.locales.clear() for locale, human in self.Locale.human_form(all=all).items(): if all: codepage = self.Locale.codepages[locale] else: codepage = "" itr = self.objects.locales.append((locale, human, codepage)) # Save iter if this is the default... if locale == self.Locale.default: self.default = itr if self.default: sel = self.objects.locale_view.get_selection() sel.select_iter(self.default) GObject.idle_add(self.objects.locale_view.scroll_to_cell, sel.get_selected_rows()[1][0]) def on_locked(self, unlockbar): """ Fired when the scene has been locked. """ GObject.idle_add(self.objects.content.set_sensitive, False) def on_unlocked(self, unlockbar): """ Fired when the scene has been unlocked. """ GObject.idle_add(self.objects.content.set_sensitive, True) def prepare_scene(self): """ Called when doing the scene setup. """ self.scene_container = self.objects.main # Check for savespace... if os.path.exists("/etc/dpkg/dpkg.cfg.d/keeptalking"): self.objects.savespace_enable.set_active(True) # Create unlockbar self.unlockbar = UnlockBar( "org.semplicelinux.keeptalking2.change-locale") self.unlockbar.connect("locked", self.on_locked) self.unlockbar.connect("unlocked", self.on_unlocked) self.objects.main.pack_start(self.unlockbar, False, False, 0) self.Locale = Locale() self.default = None # Make the locale_view treeview working... locale_renderer = Gtk.CellRendererText() self.locale_column = Gtk.TreeViewColumn("Locale", locale_renderer, text=1) self.objects.locales.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.objects.locale_view.append_column(self.locale_column) type_renderer = Gtk.CellRendererText() self.type_column = Gtk.TreeViewColumn("Type", type_renderer, text=2) self.objects.locale_view.append_column(self.type_column) # Populate the locale list GObject.idle_add(self.build_locale_list) def on_scene_called(self): """ Show the scene! """ # We are locked self.unlockbar.emit("locked") self.cancellable = Gio.Cancellable() self.RebootDialog = RebootDialog(self.cancellable) self.RebootDialog.bind_property("visible", self.scene_container, "sensitive", GObject.BindingFlags.INVERT_BOOLEAN) def on_scene_asked_to_close(self): """ Do some cleanup before returning home """ self.unlockbar.cancel_authorization() self.cancellable.cancel() return True
class Scene(quickstart.scenes.BaseScene): """ Keyboard settings. """ events = { "changed": ("model_combo", ), "cursor-changed": ("layout_view", "variant_view"), } def setxkbmap(self): """ Invokes setxkbmap and sets the currently selected layout, variant and model. """ subprocess.call( [ "setxkbmap", self.Keyboard.default_layout, self.Keyboard.default_variant if self.Keyboard.default_variant else "", "-model" if self.Keyboard.default_model else "", self.Keyboard.default_model if self.Keyboard.default_model else "" ] ) def on_model_combo_changed(self, combobox): """ Fired when the user changes the keyboard model. """ itr = self.objects.model_combo.get_active_iter() if not itr: return selected = self.objects.models.get_value(itr, 0) if selected == self.Keyboard.default_variant: return try: self.Keyboard.set(model=selected) self.default_model = itr self.setxkbmap() except: self.objects.model_combo.set_active_iter(self.default_model) def on_variant_view_cursor_changed(self, treeview): """ Fired when the user changes the variant. """ if self.building_list: return # selection sel = treeview.get_selection() if not sel: return # iter model, itr = sel.get_selected() if not itr: return selected = self.objects.variants.get_value(itr, 0) if selected == self.Keyboard.default_variant: return try: self.Keyboard.set(variant=selected) self.default_variant = itr self.setxkbmap() except: sel.select_iter(self.default_variant) def on_layout_view_cursor_changed(self, treeview): """ Fired when the user changes the locale. """ # selection sel = treeview.get_selection() if not sel: return # iter model, itr = sel.get_selected() if not itr: return selected = self.objects.layouts.get_value(itr, 0) if selected == self.Keyboard.default_layout: return # Reset default variant self.default_variant = None try: self.Keyboard.set(layout=selected, variant='') self.default = itr self.setxkbmap() except: sel.select_iter(self.default) # Rebuild variant list GObject.idle_add(self.build_variant_list, selected) def build_variant_list(self, layout): """ Populates the variant list. """ self.building_list = True self.objects.variants.clear() models, layouts = self.Keyboard.supported() variants = layouts[layout]["variants"] for variant in variants: for item, key in variant.items(): itr = self.objects.variants.append([item, key]) # Save the default variant if item == self.Keyboard.default_variant: self.default_variant = itr # No variant reciter = self.objects.variants.prepend(['', layouts[layout]["description"]]) sel = self.objects.variant_view.get_selection() if self.default_variant: sel.select_iter(self.default) else: # No variant, use reciter sel.select_iter(reciter) GObject.idle_add(self.objects.variant_view.scroll_to_cell, sel.get_selected_rows()[1][0]) self.building_list = False def build_model_list(self): """ Populates the model list. """ pc105 = None self.objects.models.clear() models = self.Keyboard.supported()[0] for item, key in models.items(): itr = self.objects.models.append([item, key]) # Save the default model if item == self.Keyboard.default_model: self.default_model = itr elif item == "pc105": # Fallback pc105 = itr if self.default_model: self.objects.model_combo.set_active_iter(self.default_model) else: self.objects.model_combo.set_active_iter(pc105) def build_layout_list(self): """ Populates the layout list. """ self.objects.layouts.clear() models, layouts = self.Keyboard.supported() for item, key in layouts.items(): itr = self.objects.layouts.append([item, key["description"]]) # Save iter if it's the default... if item == self.Keyboard.default_layout: self.default = itr if self.default: sel = self.objects.layout_view.get_selection() sel.select_iter(self.default) GObject.idle_add(self.objects.layout_view.scroll_to_cell, sel.get_selected_rows()[1][0]) # Also build the variant view! GObject.idle_add(self.build_variant_list, self.Keyboard.default_layout) def on_locked(self, unlockbar): """ Fired when the scene has been locked. """ GObject.idle_add(self.objects.content.set_sensitive, False) def on_unlocked(self, unlockbar): """ Fired when the scene has been unlocked. """ GObject.idle_add(self.objects.content.set_sensitive, True) def prepare_scene(self): """ Called when doing the scene setup. """ self.scene_container = self.objects.main # Create unlockbar self.unlockbar = UnlockBar("org.freedesktop.locale1.set-keyboard") self.unlockbar.connect("locked", self.on_locked) self.unlockbar.connect("unlocked", self.on_unlocked) self.objects.main.pack_start(self.unlockbar, False, False, 0) self.Keyboard = Keyboard() self.building_list = False self.default = None self.default_variant = None self.default_model = None # Make the layout_view treeview working... layout_renderer = Gtk.CellRendererText() self.layout_column = Gtk.TreeViewColumn("Layout", layout_renderer, text=1) self.objects.layouts.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.objects.layout_view.append_column(self.layout_column) # Do the same for the variant_view... variant_renderer = Gtk.CellRendererText() self.variant_column = Gtk.TreeViewColumn("Variant", variant_renderer, text=1) self.objects.variants.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.objects.variant_view.append_column(self.variant_column) # And something similar for the model combobox... model_renderer = Gtk.CellRendererText() self.objects.model_combo.pack_start(model_renderer, True) self.objects.model_combo.add_attribute(model_renderer, "text", 1) self.objects.models.set_sort_column_id(1, Gtk.SortType.ASCENDING) # Populate the layout list GObject.idle_add(self.build_layout_list) # Populate the model list GObject.idle_add(self.build_model_list) def on_scene_called(self): """ Show the scene! """ # We are locked self.unlockbar.emit("locked") def on_scene_asked_to_close(self): """ Do some cleanup before returning home """ self.unlockbar.cancel_authorization() return True
class Scene(quickstart.scenes.BaseScene): """ Time & Date settings. """ events = { "delete-event": ("select_timezone_dialog", ), "realize": ("select_timezone_dialog", ), "button-press-event": ("main", ), "clicked": ("time_button", "location_button", "apply_timezone"), "toggled": ("calendar_button", "ntp_enabled"), "value-changed": ("hours_adjustment", "minutes_adjustment", "seconds_adjustment"), "wrapped": ("hours", ), "output": ("hours", "minutes", "seconds") } @quickstart.threads.on_idle def build_timezone_list(self): """ Builds the timezone list. """ self.objects.timezones.clear() for item, key in self.TimeZone.supported.items(): for zone in key: zone1 = "%s/%s" % (item, zone) itr = self.objects.timezones.append([zone1, zone]) # Save the iter if it's the default if zone1 == self.TimeZone.default: # save the iter! ;) self.default = itr if self.default: sel = self.objects.timezone_treeview.get_selection() sel.select_iter(self.default) GObject.idle_add(self.objects.timezone_treeview.scroll_to_cell, sel.get_selected_rows()[1][0]) GObject.idle_add(self.objects.timezone_treeview.grab_focus) def on_apply_timezone_clicked(self, button): """ Fired when the apply_timezone button has been clicked. """ GObject.idle_add(self.objects.select_timezone_dialog.hide) # Get selected sel = self.objects.timezone_treeview.get_selection() if not sel: return model, itr = sel.get_selected() if not itr: return selected = self.objects.timezones.get_value(itr, 0) if selected == self.objects.location_button.get_label(): return # Ugly! try: self.TimeDate.SetTimezone('(sb)', selected, True) self.default = itr self.current_datetime = datetime.datetime.now() except: sel.select_iter(self.default) self.objects.location_button.set_label( self.objects.timezones.get_value(self.default, 0)) def on_select_timezone_dialog_realize(self, widget): """ Fired when the select_timezone_dialog is going to be shown. """ self.build_timezone_list() def on_select_timezone_dialog_delete_event(self, widget, event): """ Fired when the select_timezone_dialog is going to be destroyed. """ widget.hide() return True # do not destroy def on_main_button_press_event(self, eventbox, event): """ Fired when the user has clicked on the eventbox. We use this call to return to the 'read-only' mode on the time view. """ if self.objects.time_modify.props.visible and event.type == Gdk.EventType.BUTTON_PRESS: self.refresh_infos() self.objects.time_modify.hide() self.objects.time_button.show() def on_spinbutton_output(self, spinbutton): """ Fired when a spinbutton has been changed. We use this method to ensure to have two digits everytime. Code comes from http://stackoverflow.com/a/9998968 (thanks!) (not connected to anything, due to a current limitation of quickstart we will associate on_*widget*_output to this method later) """ spinbutton.set_text('{:02d}'.format( int(spinbutton.get_adjustment().get_value()))) return True on_hours_output = on_spinbutton_output on_minutes_output = on_spinbutton_output on_seconds_output = on_spinbutton_output def on_hours_wrapped(self, spinbutton): """ Fired when the hours spinbutton has been wrapped. """ if self.timezone12: if int(spinbutton.get_text()) == 1: # +1 self.hour_offset = 0 if self.hour_offset == 12 else 12 else: # -1 self.hour_offset = 12 if self.hour_offset == 0 else 0 # Reset time self.on_hours_adjustment_value_changed(spinbutton.get_adjustment()) def set_time(self): """ Actually sets the time. """ print("Setting time...") self.TimeDate.SetTime( '(xbb)', time.mktime(self.current_datetime.timetuple()) * 1000000, False, False) def on_hours_adjustment_value_changed(self, adjustment): """ Fired when the hours adjustment has been changed. """ if self.hours_input: value = int(adjustment.get_value()) if self.timezone12: value += self.hour_offset self.current_datetime = self.current_datetime.replace( hour=value if not self.timezone12 else ( 0 if value == 24 else value)) if self.timezone12: self.objects.timezone12_edit.set_text( self.current_datetime.strftime("%p")) self.set_time() def on_minutes_adjustment_value_changed(self, adjustment): """ Fired when the minutes adjustment has been changed. """ if self.minutes_input: self.current_datetime = self.current_datetime.replace( minute=int(adjustment.get_value())) self.set_time() def on_seconds_adjustment_value_changed(self, adjustment): """ Fired when the seconds adjustment has been changed. """ if self.seconds_input: self.current_datetime = self.current_datetime.replace( second=int(adjustment.get_value())) self.set_time() def on_location_button_clicked(self, button): """ Fired when the location_button has been clicked. """ GObject.idle_add(self.objects.select_timezone_dialog.present) def on_time_button_clicked(self, button): """ Fired when the time_button has been clicked. """ self.hours_input = self.minutes_input = self.seconds_input = False button.hide() self.objects.time_modify.show() # Load the adjustments with current data time = self.current_datetime.time() # Handle 12-hour timezones if not self.timezone12: # 24 hour self.objects.hours_adjustment.set_value(time.hour) self.objects.timezone12_edit.hide() else: # 12 hour self.objects.hours_adjustment.set_value(int(time.strftime("%I"))) self.objects.timezone12_edit.set_text( self.current_datetime.strftime("%p")) self.objects.minutes_adjustment.set_value(time.minute) self.objects.seconds_adjustment.set_value(time.second) def on_calendar_button_toggled(self, button): """ Fired when the calendar_button has been toggled. """ if button.get_active(): self.calendar_popover.show_all() def on_day_selected(self, calendar): """ Fired when a day in the calendar has been selected. """ date = calendar.get_date() self.current_datetime = self.current_datetime.replace(year=date[0], month=date[1] + 1, day=date[2]) self.objects.calendar_button.set_label( self.current_datetime.date().strftime("%A %d %B %Y")) # Update time if we should if self.date_input: self.set_time() def on_ntp_enabled_toggled(self, checkbox): """ Fired when the ntp_enabled checkbox has been toggled. """ if self.unlockbar.current_state == ActionResponse.UNLOCK: print("Setting NTP to %s" % checkbox.get_active()) try: self.TimeDate.SetNTP('(bb)', checkbox.get_active(), False) except GLib.GError as error: # FIXME? Here it raises FileNotFound error, I think # is some Debian bug? pass # Set sensitivity on the manual container self.objects.manual_container.set_sensitive(not checkbox.get_active()) @quickstart.threads.on_idle def refresh_infos(self): """ Refreshes the information displayed. """ _datetime = datetime.datetime.now() self.objects.time.set_text(_datetime.time().strftime("%X")) @quickstart.threads.on_idle def update_date(self): """ Updates the date. """ date = self.current_datetime.date() self.date_input = False self.calendar.select_month(date.month - 1, date.year) self.calendar.select_day(date.day) self.date_input = True @quickstart.threads.on_idle def update_time(self): """ Updates the time. """ self.current_datetime += datetime.timedelta(seconds=1) time = self.current_datetime.time() if time.hour == 00 and time.minute == 00 and time.second == 00: # Day changed self.update_date() # Update the current visible time object if self.objects.time_modify.props.visible: if time.minute == 00 and time.second == 00: self.hours_input = False self.objects.hours_adjustment.set_value(time.hour) if time.second == 00: self.minutes_input = False self.objects.minutes_adjustment.set_value(time.minute) self.seconds_input = False self.objects.seconds_adjustment.set_value(time.second) self.hours_input = self.minutes_input = self.seconds_input = True else: self.objects.time.set_text(time.strftime("%X")) def on_locked(self, unlockbar): """ Fired when the user (or policykit) has locked the special temporary privilegies. """ # Locked, disable sensitivity on everything... self.objects.container.set_sensitive(False) def on_unlocked(self, unlockbar): """ Fired when the user has got the special temporary privilegies. """ # Unlocked, re-set sensitivity self.objects.container.set_sensitive(True) def prepare_scene(self): """ Called when doing the scene setup. """ self.scene_container = self.objects.main self.default = None self.TimeZone = TimeZone() self.hour_offset = 0 self.timezone12 = None # Create unlockbar self.unlockbar = UnlockBar("org.freedesktop.timedate1.set-time") self.unlockbar.connect("locked", self.on_locked) self.unlockbar.connect("unlocked", self.on_unlocked) self.objects.main_box.pack_start(self.unlockbar, False, False, 0) # Enter in the bus self.bus_cancellable = Gio.Cancellable() self.bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, self.bus_cancellable) self.TimeDate = Gio.DBusProxy.new_sync(self.bus, 0, None, BUS_NAME, "/org/freedesktop/timedate1", BUS_NAME, self.bus_cancellable) self.TimeDateProperties = Gio.DBusProxy.new_sync( self.bus, 0, None, BUS_NAME, "/org/freedesktop/timedate1", "org.freedesktop.DBus.Properties", self.bus_cancellable ) # Really we should create a new proxy to get the properties?! #self.refresh_infos() # Set-up select timezone dialog self.objects.timezone_treeview.append_column( Gtk.TreeViewColumn("Timezone", Gtk.CellRendererText(), text=0)) self.objects.timezones.set_sort_column_id(0, Gtk.SortType.ASCENDING) # Create calendar popover self.calendar = Gtk.Calendar() self.calendar.connect("day-selected", self.on_day_selected) self.calendar_popover = Gtk.Popover.new(self.objects.calendar_button) self.calendar_popover.set_modal(True) self.calendar_popover.connect( "closed", lambda x: self.objects.calendar_button.set_active(False)) self.calendar_popover.add(self.calendar) # Set appropriate font size and weight context = self.objects.time.create_pango_context() desc = context.get_font_description() desc.set_weight(Pango.Weight.LIGHT) # Weight desc.set_size(Pango.SCALE * 80) # Size self.objects.time.override_font(desc) self.objects.hours.override_font(desc) self.objects.minutes.override_font(desc) self.objects.seconds.override_font(desc) self.objects.timezone12_edit.override_font(desc) # Set mask on the main eventbox self.objects.main.set_events(Gdk.EventMask.BUTTON_PRESS_MASK) # Styling self.objects.time_button.get_style_context().add_class("no-borders") self.objects.location_button.get_style_context().add_class( "no-borders") self.objects.calendar_button.get_style_context().add_class( "no-borders") def on_scene_called(self): """ Called when switching to this scene. We will handle here all timeouts to ensure we syncronize the time label with the actual time. """ self.objects.main.show_all() self.objects.time_modify.hide() # We are locked self.unlockbar.emit("locked") self.current_datetime = datetime.datetime.now() self.timezone12 = (not self.current_datetime.strftime("%p") == "") adj = self.objects.hours.get_adjustment() if self.timezone12: adj.set_upper(12) adj.set_lower(1) else: adj.set_upper(23) adj.set_lower(0) if self.current_datetime.time().hour > 12: self.hour_offset = 12 self.update_date() self.update_time() # NTP ntp = bool(self.TimeDateProperties.Get('(ss)', BUS_NAME, 'NTP')) self.objects.ntp_enabled.set_active(ntp) # Timezone self.objects.location_button.set_label( self.TimeDateProperties.Get('(ss)', BUS_NAME, 'Timezone')) self.label_timeout = GLib.timeout_add_seconds(1, self.update_time) def on_scene_asked_to_close(self): """ Do some cleanup before returning home """ GLib.source_remove(self.label_timeout) self.unlockbar.cancel_authorization() self.bus_cancellable.cancel() return True
class Scene(quickstart.scenes.BaseScene): """ Time & Date settings. """ events = { "delete-event" : ("select_timezone_dialog",), "realize": ("select_timezone_dialog",), "button-press-event" : ("main",), "clicked" : ("time_button", "location_button", "apply_timezone"), "toggled" : ("calendar_button", "ntp_enabled"), "value-changed" : ("hours_adjustment", "minutes_adjustment", "seconds_adjustment"), "wrapped" : ("hours",), "output" : ("hours", "minutes", "seconds") } @quickstart.threads.on_idle def build_timezone_list(self): """ Builds the timezone list. """ self.objects.timezones.clear() for item, key in self.TimeZone.supported.items(): for zone in key: zone1 = "%s/%s" % (item, zone) itr = self.objects.timezones.append([zone1, zone]) # Save the iter if it's the default if zone1 == self.TimeZone.default: # save the iter! ;) self.default = itr if self.default: sel = self.objects.timezone_treeview.get_selection() sel.select_iter(self.default) GObject.idle_add(self.objects.timezone_treeview.scroll_to_cell, sel.get_selected_rows()[1][0]) GObject.idle_add(self.objects.timezone_treeview.grab_focus) def on_apply_timezone_clicked(self, button): """ Fired when the apply_timezone button has been clicked. """ GObject.idle_add(self.objects.select_timezone_dialog.hide) # Get selected sel = self.objects.timezone_treeview.get_selection() if not sel: return model, itr = sel.get_selected() if not itr: return selected = self.objects.timezones.get_value(itr, 0) if selected == self.objects.location_button.get_label(): return # Ugly! try: self.TimeDate.SetTimezone( '(sb)', selected, True ) self.default = itr self.current_datetime = datetime.datetime.now() except: sel.select_iter(self.default) self.objects.location_button.set_label(self.objects.timezones.get_value(self.default, 0)) def on_select_timezone_dialog_realize(self, widget): """ Fired when the select_timezone_dialog is going to be shown. """ self.build_timezone_list() def on_select_timezone_dialog_delete_event(self, widget, event): """ Fired when the select_timezone_dialog is going to be destroyed. """ widget.hide() return True # do not destroy def on_main_button_press_event(self, eventbox, event): """ Fired when the user has clicked on the eventbox. We use this call to return to the 'read-only' mode on the time view. """ if self.objects.time_modify.props.visible and event.type == Gdk.EventType.BUTTON_PRESS: self.refresh_infos() self.objects.time_modify.hide() self.objects.time_button.show() def on_spinbutton_output(self, spinbutton): """ Fired when a spinbutton has been changed. We use this method to ensure to have two digits everytime. Code comes from http://stackoverflow.com/a/9998968 (thanks!) (not connected to anything, due to a current limitation of quickstart we will associate on_*widget*_output to this method later) """ spinbutton.set_text('{:02d}'.format(int(spinbutton.get_adjustment().get_value()))) return True on_hours_output = on_spinbutton_output on_minutes_output = on_spinbutton_output on_seconds_output = on_spinbutton_output def on_hours_wrapped(self, spinbutton): """ Fired when the hours spinbutton has been wrapped. """ if self.timezone12: if int(spinbutton.get_text()) == 1: # +1 self.hour_offset = 0 if self.hour_offset == 12 else 12 else: # -1 self.hour_offset = 12 if self.hour_offset == 0 else 0 # Reset time self.on_hours_adjustment_value_changed(spinbutton.get_adjustment()) def set_time(self): """ Actually sets the time. """ print("Setting time...") self.TimeDate.SetTime('(xbb)', time.mktime(self.current_datetime.timetuple()) * 1000000, False, False) def on_hours_adjustment_value_changed(self, adjustment): """ Fired when the hours adjustment has been changed. """ if self.hours_input: value = int(adjustment.get_value()) if self.timezone12: value += self.hour_offset self.current_datetime = self.current_datetime.replace( hour=value if not self.timezone12 else ( 0 if value == 24 else value ) ) if self.timezone12: self.objects.timezone12_edit.set_text(self.current_datetime.strftime("%p")) self.set_time() def on_minutes_adjustment_value_changed(self, adjustment): """ Fired when the minutes adjustment has been changed. """ if self.minutes_input: self.current_datetime = self.current_datetime.replace(minute=int(adjustment.get_value())) self.set_time() def on_seconds_adjustment_value_changed(self, adjustment): """ Fired when the seconds adjustment has been changed. """ if self.seconds_input: self.current_datetime = self.current_datetime.replace(second=int(adjustment.get_value())) self.set_time() def on_location_button_clicked(self, button): """ Fired when the location_button has been clicked. """ GObject.idle_add(self.objects.select_timezone_dialog.present) def on_time_button_clicked(self, button): """ Fired when the time_button has been clicked. """ self.hours_input = self.minutes_input = self.seconds_input = False button.hide() self.objects.time_modify.show() # Load the adjustments with current data time = self.current_datetime.time() # Handle 12-hour timezones if not self.timezone12: # 24 hour self.objects.hours_adjustment.set_value(time.hour) self.objects.timezone12_edit.hide() else: # 12 hour self.objects.hours_adjustment.set_value(int(time.strftime("%I"))) self.objects.timezone12_edit.set_text(self.current_datetime.strftime("%p")) self.objects.minutes_adjustment.set_value(time.minute) self.objects.seconds_adjustment.set_value(time.second) def on_calendar_button_toggled(self, button): """ Fired when the calendar_button has been toggled. """ if button.get_active(): self.calendar_popover.show_all() def on_day_selected(self, calendar): """ Fired when a day in the calendar has been selected. """ date = calendar.get_date() self.current_datetime = self.current_datetime.replace( year=date[0], month=date[1]+1, day=date[2] ) self.objects.calendar_button.set_label(self.current_datetime.date().strftime("%A %d %B %Y")) # Update time if we should if self.date_input: self.set_time() def on_ntp_enabled_toggled(self, checkbox): """ Fired when the ntp_enabled checkbox has been toggled. """ if self.unlockbar.current_state == ActionResponse.UNLOCK: print("Setting NTP to %s" % checkbox.get_active()) try: self.TimeDate.SetNTP('(bb)', checkbox.get_active(), False) except GLib.GError as error: # FIXME? Here it raises FileNotFound error, I think # is some Debian bug? pass # Set sensitivity on the manual container self.objects.manual_container.set_sensitive(not checkbox.get_active()) @quickstart.threads.on_idle def refresh_infos(self): """ Refreshes the information displayed. """ _datetime = datetime.datetime.now() self.objects.time.set_text(_datetime.time().strftime("%X")) @quickstart.threads.on_idle def update_date(self): """ Updates the date. """ date = self.current_datetime.date() self.date_input = False self.calendar.select_month(date.month-1, date.year) self.calendar.select_day(date.day) self.date_input = True @quickstart.threads.on_idle def update_time(self): """ Updates the time. """ self.current_datetime += datetime.timedelta(seconds=1) time = self.current_datetime.time() if time.hour == 00 and time.minute == 00 and time.second == 00: # Day changed self.update_date() # Update the current visible time object if self.objects.time_modify.props.visible: if time.minute == 00 and time.second == 00: self.hours_input = False self.objects.hours_adjustment.set_value(time.hour) if time.second == 00: self.minutes_input = False self.objects.minutes_adjustment.set_value(time.minute) self.seconds_input = False self.objects.seconds_adjustment.set_value(time.second) self.hours_input = self.minutes_input = self.seconds_input = True else: self.objects.time.set_text(time.strftime("%X")) def on_locked(self, unlockbar): """ Fired when the user (or policykit) has locked the special temporary privilegies. """ # Locked, disable sensitivity on everything... self.objects.container.set_sensitive(False) def on_unlocked(self, unlockbar): """ Fired when the user has got the special temporary privilegies. """ # Unlocked, re-set sensitivity self.objects.container.set_sensitive(True) def prepare_scene(self): """ Called when doing the scene setup. """ self.scene_container = self.objects.main self.default = None self.TimeZone = TimeZone() self.hour_offset = 0 self.timezone12 = None # Create unlockbar self.unlockbar = UnlockBar("org.freedesktop.timedate1.set-time") self.unlockbar.connect("locked", self.on_locked) self.unlockbar.connect("unlocked", self.on_unlocked) self.objects.main_box.pack_start(self.unlockbar, False, False, 0) # Enter in the bus self.bus_cancellable = Gio.Cancellable() self.bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, self.bus_cancellable) self.TimeDate = Gio.DBusProxy.new_sync( self.bus, 0, None, BUS_NAME, "/org/freedesktop/timedate1", BUS_NAME, self.bus_cancellable ) self.TimeDateProperties = Gio.DBusProxy.new_sync( self.bus, 0, None, BUS_NAME, "/org/freedesktop/timedate1", "org.freedesktop.DBus.Properties", self.bus_cancellable ) # Really we should create a new proxy to get the properties?! #self.refresh_infos() # Set-up select timezone dialog self.objects.timezone_treeview.append_column( Gtk.TreeViewColumn( "Timezone", Gtk.CellRendererText(), text=0 ) ) self.objects.timezones.set_sort_column_id(0, Gtk.SortType.ASCENDING) # Create calendar popover self.calendar = Gtk.Calendar() self.calendar.connect("day-selected", self.on_day_selected) self.calendar_popover = Gtk.Popover.new(self.objects.calendar_button) self.calendar_popover.set_modal(True) self.calendar_popover.connect("closed", lambda x: self.objects.calendar_button.set_active(False)) self.calendar_popover.add(self.calendar) # Set appropriate font size and weight context = self.objects.time.create_pango_context() desc = context.get_font_description() desc.set_weight(Pango.Weight.LIGHT) # Weight desc.set_size(Pango.SCALE*80) # Size self.objects.time.override_font(desc) self.objects.hours.override_font(desc) self.objects.minutes.override_font(desc) self.objects.seconds.override_font(desc) self.objects.timezone12_edit.override_font(desc) # Set mask on the main eventbox self.objects.main.set_events(Gdk.EventMask.BUTTON_PRESS_MASK) # Styling self.objects.time_button.get_style_context().add_class("no-borders") self.objects.location_button.get_style_context().add_class("no-borders") self.objects.calendar_button.get_style_context().add_class("no-borders") def on_scene_called(self): """ Called when switching to this scene. We will handle here all timeouts to ensure we syncronize the time label with the actual time. """ self.objects.main.show_all() self.objects.time_modify.hide() # We are locked self.unlockbar.emit("locked") self.current_datetime = datetime.datetime.now() self.timezone12 = (not self.current_datetime.strftime("%p") == "") adj = self.objects.hours.get_adjustment() if self.timezone12: adj.set_upper(12) adj.set_lower(1) else: adj.set_upper(23) adj.set_lower(0) if self.current_datetime.time().hour > 12: self.hour_offset = 12 self.update_date() self.update_time() # NTP ntp = bool(self.TimeDateProperties.Get('(ss)', BUS_NAME, 'NTP')) self.objects.ntp_enabled.set_active(ntp) # Timezone self.objects.location_button.set_label(self.TimeDateProperties.Get('(ss)', BUS_NAME, 'Timezone')) self.label_timeout = GLib.timeout_add_seconds(1, self.update_time) def on_scene_asked_to_close(self): """ Do some cleanup before returning home """ GLib.source_remove(self.label_timeout) self.unlockbar.cancel_authorization() self.bus_cancellable.cancel() return True