diff --git a/bin/sugar.in b/bin/sugar.in index aebb8978ab..366ede2eec 100644 --- a/bin/sugar.in +++ b/bin/sugar.in @@ -20,6 +20,10 @@ if test -z "$SUGAR_SCALING"; then export SUGAR_SCALING=72 fi +if test -z "$SUGAR_GROUP_LABELS"; then + export SUGAR_GROUP_LABELS="$sugardatadir/group-labels.defaults" +fi + if test -z "$SUGAR_MIME_DEFAULTS"; then export SUGAR_MIME_DEFAULTS="$sugardatadir/mime.defaults" fi diff --git a/data/Makefile.am b/data/Makefile.am index 01ceb525c8..2f7b6d5a99 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -11,6 +11,7 @@ sugar-100.gtkrc: gtkrc.em sugardir = $(pkgdatadir)/data sugar_DATA = \ activities.defaults \ + group-labels.defaults \ ISO-639-2_utf-8.txt \ kbdconfig \ mime.defaults \ diff --git a/data/group-labels.defaults b/data/group-labels.defaults new file mode 100644 index 0000000000..9bf3569729 --- /dev/null +++ b/data/group-labels.defaults @@ -0,0 +1 @@ +{"group-label": "Select grade:", "group-items": [{"female-icon": "female-1", "male-icon": "male-1", "label": "Preschool", "age": 4}, {"female-icon": "female-1", "male-icon": "male-1", "label": "Kindergarten", "age": 5}, {"female-icon": "female-2", "male-icon": "male-2", "label": "1st Grade", "age": 6}, {"female-icon": "female-3", "male-icon": "male-3", "label": "2nd Grade", "age": 7}, {"female-icon": "female-4", "male-icon": "male-4", "label": "3rd Grade", "age": 8}, {"female-icon": "female-5", "male-icon": "male-5", "label": "4th Grade", "age": 9}, {"female-icon": "female-5", "male-icon": "male-5", "label": "5th Grade", "age": 10}, {"female-icon": "female-6", "male-icon": "male-6", "label": "6th Grade", "age": 11}, {"female-icon": "female-6", "male-icon": "male-6", "label": "7th Grade", "age": 12}, {"female-icon": "female-7", "male-icon": "male-7", "label": "High School", "age": 13}, {"female-icon": "female-7", "male-icon": "male-7", "label": "Adult", "age": 25}]} diff --git a/data/org.sugarlabs.gschema.xml b/data/org.sugarlabs.gschema.xml index 3ae041cb49..1971c1b22f 100644 --- a/data/org.sugarlabs.gschema.xml +++ b/data/org.sugarlabs.gschema.xml @@ -82,6 +82,11 @@ User Birth Timestamp Birth timestamp (seconds since the epoch) + + '' + Group Label + Label associated with age, e.g., '2nd Grade' + diff --git a/extensions/cpsection/aboutme/model.py b/extensions/cpsection/aboutme/model.py index a3d89bca76..e60e9c5fa1 100644 --- a/extensions/cpsection/aboutme/model.py +++ b/extensions/cpsection/aboutme/model.py @@ -24,9 +24,6 @@ from sugar3 import profile -from jarabe.intro.window import calculate_birth_timestamp, calculate_age -from jarabe.intro.agepicker import AGES - _COLORS = { 'red': {'dark': '#b20008', 'medium': '#e6000a', 'light': '#ffadce'}, 'orange': {'dark': '#9a5200', 'medium': '#c97e00', 'light': '#ffc169'}, @@ -145,71 +142,3 @@ def set_color_xo(color): client = GConf.Client.get_default() client.set_string('/desktop/sugar/user/color', color) return 1 - - -def get_gender(): - settings = Gio.Settings('org.sugarlabs.user') - return settings.get_string('gender') - - -def print_gender(): - print get_gender() - - -def set_gender(gender): - """Set the gender, e.g. 'female' - """ - if not gender: - gender = '' # default value in gsettings indicates no gender selected - elif gender not in ['male', 'female', '']: - raise ValueError(_('Gender must be male or female.')) - - settings = Gio.Settings('org.sugarlabs.user') - settings.set_string('gender', gender) - return - - -def get_age(): - settings = Gio.Settings('org.sugarlabs.user') - birth_timestamp = settings.get_int('birth-timestamp') - - if birth_timestamp == 0: - return None - - birth_age = calculate_age(birth_timestamp) - - age = (AGES[-2] + AGES[-1]) / 2. - if birth_age >= age: - return AGES[-1] - - for i in range(len(AGES) - 1): - age = (AGES[i] + AGES[i + 1]) / 2. - if birth_age < age: - return AGES[i] - - return None - - -def print_age(): - print get_age() - - -def set_age(age): - """Set the age and an approximate birth timestamp - age: e.g. 8 - birth_timestamp: time - age * #seconds per year - """ - try: - i = int(age) - except ValueError, e: - logging.error('set_age: %s' % (e)) - i = None - - if i is None or i < 1: - raise ValueError(_('Age must be a positive integer.')) - - birth_timestamp = calculate_birth_timestamp(age) - - settings = Gio.Settings('org.sugarlabs.user') - settings.set_int('birth-timestamp', birth_timestamp) - return diff --git a/extensions/cpsection/aboutme/view.py b/extensions/cpsection/aboutme/view.py index 287bd02979..e4b95810b3 100644 --- a/extensions/cpsection/aboutme/view.py +++ b/extensions/cpsection/aboutme/view.py @@ -18,8 +18,10 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from gi.repository import Gtk +from gi.repository import Gdk from gi.repository import GObject from gettext import gettext as _ +import logging from sugar3.graphics import style from sugar3.graphics.xocolor import XoColor, colors @@ -27,7 +29,8 @@ from jarabe.controlpanel.sectionview import SectionView from jarabe.controlpanel.inlinealert import InlineAlert -from jarabe.intro.agepicker import AGES, AGE_LABELS +from jarabe.intro.agepicker import AgePicker, save_age, load_age +from jarabe.intro.genderpicker import GenderPicker, save_gender, load_gender _STROKE_COLOR = 0 @@ -149,94 +152,11 @@ def __pressed_cb(self, button, event, picker): self.color_changed_signal.emit(self._color) -class GenderPicker(EventIcon): - gender_changed_signal = GObject.Signal('gender-changed', - arg_types=([str])) - - def __init__(self, color, gender): - EventIcon.__init__(self, icon_name='%s-6' % (gender), - pixel_size=style.XLARGE_ICON_SIZE) - self._gender = gender - self._color = color - - self.set_gender() - - self.connect('button_press_event', self.__pressed_cb) - - def set_color(self, color, gender): - self._color = color - self.set_gender(gender) - - def set_gender(self, gender=''): - if gender is not '' and self._gender == gender: - self.props.xo_color = self._color - else: - self.props.xo_color = _NOCOLOR - - gender = GObject.property(type=object, setter=set_gender) - - def __pressed_cb(self, button, event): - self.gender_changed_signal.emit(self._gender) - - -class AgePicker(Gtk.Grid): - - age_changed_signal = GObject.Signal('age-changed', - arg_types=([int])) - - def __init__(self, color, gender, age): - Gtk.Grid.__init__(self) - self._color = color - self._gender = gender - self._age = age - - if self._gender is '': - # Used for graphic only; does not set user's gender preference. - self._gender = 'female' - - self._icon = EventIcon(icon_name='%s-%d' % (self._gender, self._age), - pixel_size=style.LARGE_ICON_SIZE) - self._icon.connect('button-press-event', self.__pressed_cb) - self.attach(self._icon, 0, 0, 1, 1) - self._icon.show() - - label = Gtk.Label() - label.set_text(AGE_LABELS[self._age]) - self.attach(label, 0, 1, 1, 1) - label.show() - - self.set_age() - - def set_color(self, color, age): - self._color = color - self.set_age(age) - - def set_age(self, age=None): - if age in AGES: - age_index = AGES.index(age) - else: - age_index = None - - if age_index == self._age: - self._icon.props.xo_color = self._color - else: - self._icon.props.xo_color = _NOCOLOR - self._icon.show() - - age = GObject.property(type=object, setter=set_age) - - def set_gender(self, gender): - self._icon.set_icon_name('%s-%d' % (gender, self._age)) - self._icon.show() - - gender = GObject.property(type=object, setter=set_gender) - - def __pressed_cb(self, button, event): - self.age_changed_signal.emit(self._age) - - class AboutMe(SectionView): + age_changed_signal = GObject.Signal('age-changed', arg_types=([int])) + gender_changed_signal = GObject.Signal('gender-changed', arg_types=([str])) + def __init__(self, model, alerts): SectionView.__init__(self) @@ -272,11 +192,10 @@ def __init__(self, model, alerts): for picker in self._pickers.values(): picker.connect('color-changed', self.__color_changed_cb) - self._female_picker.connect('gender-changed', self.__gender_changed_cb) - self._male_picker.connect('gender-changed', self.__gender_changed_cb) + self._gender_pickers.connect('gender-changed', + self.__gender_changed_cb) + self._age_pickers.connect('age-changed', self.__age_changed_cb) - for picker in self._age_pickers: - picker.connect('age-changed', self.__age_changed_cb) def _setup_nick(self): grid = Gtk.Grid() @@ -366,7 +285,9 @@ def _setup_color(self): center_in_panel.show() def _setup_gender(self): - self._gender = self._model.get_gender() + self._saved_gender = load_gender() + + self._gender_pickers = GenderPicker() grid = Gtk.Grid() grid.set_row_spacing(style.DEFAULT_SPACING) @@ -378,15 +299,8 @@ def _setup_gender(self): grid.attach(label_gender, 0, 0, 1, 1) label_gender.show() - self._female_picker = GenderPicker(self._color, 'female') - grid.attach(self._female_picker, 0, 1, 1, 1) - self._female_picker.props.gender = self._gender - self._female_picker.show() - - self._male_picker = GenderPicker(self._color, 'male') - grid.attach(self._male_picker, 1, 1, 1, 1) - self._male_picker.props.gender = self._gender - self._male_picker.show() + grid.attach(self._gender_pickers, 0, 1, 1, 1) + self._gender_pickers.show() center_in_panel = Gtk.Alignment.new(0.5, 0, 0, 0) center_in_panel.add(grid) @@ -396,26 +310,30 @@ def _setup_gender(self): center_in_panel.show() def _setup_age(self): - self._age = self._model.get_age() + self._saved_age = load_age() grid = Gtk.Grid() grid.set_row_spacing(style.DEFAULT_SPACING) grid.set_column_spacing(style.DEFAULT_SPACING) - self._age_pickers = [] - for i in range(len(AGES)): - self._age_pickers.append(AgePicker(self._color, self._gender, i)) + self._age_pickers = AgePicker(self._saved_gender) + center_in_panel = Gtk.Alignment.new(0.5, 0, 0, 0) + center_in_panel.add(self._age_pickers) + self._age_pickers.show() + + label = self._age_pickers.get_label() - label_age = Gtk.Label(label=_('Select age:')) + label_age = Gtk.Label(label=_(label)) label_age.modify_fg(Gtk.StateType.NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) - grid.attach(label_age, 0, 0, 1, 1) + left_align = Gtk.Alignment.new(0, 0, 0, 0) + left_align.add(label_age) label_age.show() + grid.attach(left_align, 0, 0, 1, 1) + left_align.show() - for i in range(len(AGES)): - grid.attach(self._age_pickers[i], i, 1, 1, 1) - self._age_pickers[i].set_age(self._age) - self._age_pickers[i].show() + grid.attach(center_in_panel, 0, 1, 1, 1) + center_in_panel.show() center_in_panel = Gtk.Alignment.new(0.5, 0, 0, 0) center_in_panel.add(grid) @@ -431,16 +349,15 @@ def undo(self): self._nick_alert.hide() self._color_alert.hide() - self._model.set_gender(self._gender) - self._model.set_age(self._age) + # Undo gender or age changes + save_gender(self._saved_gender) + save_age(self._saved_age) def _update_pickers(self, color): for picker in self._pickers.values(): picker.props.color = color - self._female_picker.set_color(color, self._gender) - self._male_picker.set_color(color, self._gender) - for i in range(len(AGES)): - self._age_pickers[i].set_color(color, self._age) + self._gender_pickers.update_color(color) + self._age_pickers.update_color(color) def _validate(self): if self._nick_valid and self._color_valid: @@ -498,16 +415,9 @@ def __color_changed_cb(self, colorpicker, color): return False def __gender_changed_cb(self, genderpicker, gender): - self._model.set_gender(gender) - self._female_picker.props.gender = gender - self._female_picker.props.gender = gender - self._male_picker.props.gender = gender - for i in range(len(AGES)): - self._age_pickers[i].props.gender = gender + save_gender(gender) + self._age_pickers.update_gender(gender) return False - def __age_changed_cb(self, agepicker, age): - self._model.set_age(AGES[age]) - for i in range(len(AGES)): - self._age_pickers[i].props.age = AGES[age] - return False + def __age_changed_cb(self, event, age): + save_age(age) diff --git a/src/jarabe/intro/__init__.py b/src/jarabe/intro/__init__.py index 5c243025d1..2766f01198 100644 --- a/src/jarabe/intro/__init__.py +++ b/src/jarabe/intro/__init__.py @@ -1,5 +1,7 @@ import os +from gi.repository import Gio + from sugar3 import env from sugar3.profile import get_profile @@ -12,3 +14,14 @@ def check_profile(): profile.convert_profile() return profile.is_valid() + + +def check_group_label(): + settings = Gio.Settings('org.sugarlabs.user') + if len(settings.get_string('group-label')) > 0: + return True + + # DEPRECATED + from gi.repository import GConf + client = GConf.Client.get_default() + return client.get_string('/desktop/sugar/user/group') is not None diff --git a/src/jarabe/intro/agepicker.py b/src/jarabe/intro/agepicker.py index 1e861654d5..87d1a73b63 100644 --- a/src/jarabe/intro/agepicker.py +++ b/src/jarabe/intro/agepicker.py @@ -17,6 +17,14 @@ from gi.repository import Gtk from gi.repository import Gdk +from gi.repository import Gio +from gi.repository import GObject + +import os +import json +import time +import math +import logging from gettext import gettext as _ @@ -24,65 +32,290 @@ from sugar3.graphics import style from sugar3.graphics.xocolor import XoColor -AGES = [3, 5, 7, 9, 11, 12, 15, 25] -AGE_LABELS = [_('0-3'), _('4-5'), _('6-7'), _('8-9'), _('10-11'), _('12'), - _('13-17'), _('Adult')] +from jarabe.intro.genderpicker import GENDERS + +_group_labels = None +_SECONDS_PER_YEAR = 365 * 24 * 60 * 60. + + +def calculate_birth_timestamp(age): + age_in_seconds = age * _SECONDS_PER_YEAR + birth_timestamp = int(time.time() - age_in_seconds) + return birth_timestamp + + +def calculate_age(birth_timestamp): + age_in_seconds = time.time() - birth_timestamp + # Round to nearest int + age = int(math.floor(age_in_seconds / _SECONDS_PER_YEAR) + 0.5) + return age + + +def age_to_index(age): + group_labels = get_group_labels() + + if age is None: + return int(len(group_labels.AGES) / 2.0) + + age2 = age * 2 + for i in range(len(group_labels.AGES) - 1): + if age2 < (group_labels.AGES[i] + group_labels.AGES[i + 1]): + return i + + return len(group_labels.AGES) - 1 + + +def age_to_group_label(age): + group_labels = get_group_labels() + + return group_labels.LABELS[age_to_index(age)] + + +def group_label_to_age(label): + group_labels = get_group_labels() + + if labels not in group_labels.LABELS: + return None + + return group_labels.AGES[group_labels.LABELS.index(label)] + + +def load_age(): + group_labels = get_group_labels() + + settings = Gio.Settings('org.sugarlabs.user') + birth_timestamp = settings.get_int('birth-timestamp') + + if birth_timestamp == 0: + return None + + birth_age = calculate_age(birth_timestamp) + + age = (group_labels.AGES[-2] + group_labels.AGES[-1]) / 2. + if birth_age >= age: + return group_labels.AGES[-1] + + for i in range(len(group_labels.AGES) - 1): + age = (group_labels.AGES[i] + group_labels.AGES[i + 1]) / 2. + if birth_age < age: + return group_labels.AGES[i] + + return None + + +def save_age(age): + birth_timestamp = calculate_birth_timestamp(age) + settings = Gio.Settings('org.sugarlabs.user') + settings.set_int('birth-timestamp', birth_timestamp) + + # Record the label so we know it was set + settings.set_string('group-label', age_to_group_label(age)) + + # DEPRECATED + from gi.repository import GConf + client = GConf.Client.get_default() + client.set_int('/desktop/sugar/user/birth_timestamp', birth_timestamp) + + +class GroupLabels(): + GROUP_LABEL = [] + AGES = [] + LABELS = [] + ICONS = [] + + def __init__(self): + f = open(os.environ['SUGAR_GROUP_LABELS'], 'r') + json_data = f.read() + f.close() + group_labels = json.loads(json_data) + self.GROUP_LABEL = group_labels['group-label'] + for item in group_labels['group-items']: + self.ICONS.append([item['female-icon'], item['male-icon']]) + self.LABELS.append(_(item['label'])) + self.AGES.append(item['age']) + + +def get_group_labels(): + global _group_labels + + if not _group_labels: + _group_labels = GroupLabels() + + return _group_labels + + +class Picker(Gtk.Grid): + + def __init__(self, icon, label): + Gtk.Grid.__init__(self) + + self._button = EventIcon(pixel_size=style.LARGE_ICON_SIZE, + icon_name=icon) + self.attach(self._button, 0, 0, 1, 1) + self._button.hide() + + self._label = Gtk.Label(label) + self.attach(self._label, 0, 1, 1, 1) + self._label.hide() + + def show_all(self): + self._button.show() + self._label.show() + self.show() + + def hide_all(self): + self._button.hide() + self._label.hide() + self.hide() + + def connect(self, callback, arg): + self._button.connect('button-press-event', callback, arg) + + def set_color(self, color): + self._button.xo_color = color + + def set_icon(self, icon): + self._button.set_icon_name(icon) class AgePicker(Gtk.Grid): - def __init__(self, gender): + age_changed_signal = GObject.Signal('age-changed', arg_types=([int])) + + def __init__(self, gender, page=None): Gtk.Grid.__init__(self) + self.set_row_spacing(style.DEFAULT_SPACING) self.set_column_spacing(style.DEFAULT_SPACING) + self._group_labels = get_group_labels() + + self._page = page self._gender = gender - self._age = 5 - self._buttons = [] + self._age = self.get_age() + self._pickers = [] self._nocolor = XoColor('#010101,#ffffff') self._color = XoColor() - if self._gender is None or self._gender == 'None': - self._gender = 'male' + if self._gender not in GENDERS: + self._gender = 'female' + + gender_index = GENDERS.index(self._gender) + age_index = age_to_index(self._age) + + width = Gdk.Screen.width() + + num_ages = len(self._group_labels.AGES) + for i in range(num_ages): + self._pickers.append( + Picker(self._group_labels.ICONS[i][gender_index], + _(self._group_labels.LABELS[i]))) + self._pickers[i].connect(self._button_press_cb, i) + + self._fixed = Gtk.Fixed() + fixed_size = width - 4 * style.GRID_CELL_SIZE + self._fixed.set_size_request(fixed_size, -1) + self.attach(self._fixed, 0, 0, 1, 1) + self._fixed.show() - for i in range(len(AGES)): - self._buttons.append( - EventIcon(pixel_size=style.LARGE_ICON_SIZE, - icon_name='%s-%d' % (self._gender, i))) - self._buttons[-1].show() - self._buttons[-1].connect('button-press-event', - self._button_press_cb, i) + self._age_adj = Gtk.Adjustment(value=age_index, lower=0, + upper=num_ages - 1, step_incr=1, + page_incr=3, page_size=0) + self._age_adj.connect('value-changed', self.__age_adj_changed_cb) - label = Gtk.Label() - label.set_text(AGE_LABELS[i]) - label.show() + self._age_slider = Gtk.HScale() + self._age_slider.set_draw_value(False) + self._age_slider.set_adjustment(self._age_adj) + self.attach(self._age_slider, 0, 1, 1, 1) - self.attach(self._buttons[-1], i, 0, 1, 1) - self.attach(label, i, 1, 1, 1) + for i in range(num_ages): + self._fixed.put(self._pickers[i], 0, 0) - def _button_press_cb(self, widget, event, age): + self._configure(width) + + Gdk.Screen.get_default().connect('size-changed', self._configure_cb) + + def _configure_cb(self, event=None): + width = Gdk.Screen.width() + self._configure(width) + + def _configure(self, width): + fixed_size = width - 4 * style.GRID_CELL_SIZE + self._fixed.set_size_request(fixed_size, -1) + + num_ages = len(self._group_labels.AGES) + + dx = int((fixed_size - style.LARGE_ICON_SIZE) / (num_ages - 1)) + for i in range(num_ages): + self._fixed.move(self._pickers[i], dx * i, 0) + + if num_ages + 2 < width / style.LARGE_ICON_SIZE: + for i in range(num_ages): + self._pickers[i].show_all() + self._age_slider.hide() + else: + self._age_slider.show() + value = self._age_adj.get_value() + self._set_age_picker(int(value + 0.5)) + + def get_label(self): + return self._group_labels.GROUP_LABEL + + def _set_age_picker(self, age_index): + for i in range(len(self._group_labels.AGES)): + if i == age_index: + self._pickers[i].show_all() + else: + self._pickers[i].hide_all() + self._do_selected(age_index) + + def __age_adj_changed_cb(self, widget): + value = self._age_adj.get_value() + self._set_age_picker(int(value + 0.5)) + + def _do_selected(self, age_index): + if self._age is not None: + i = age_to_index(self._age) + self._pickers[i].set_color(self._nocolor) + self._set_age(self._group_labels.AGES[age_index]) + self._pickers[age_index].set_color(self._color) + + def _button_press_cb(self, widget, event, age_index): if event.button == 1 and event.type == Gdk.EventType.BUTTON_PRESS: - if self._age is not None: - self._buttons[self._age].xo_color = self._nocolor - self._set_age(age) - self._buttons[age].xo_color = self._color + self._do_selected(age_index) def get_age(self): - if self._age is None: - return None - else: - return AGES[self._age] + if self._page is None: + return load_age() + elif hasattr(self, '_age'): + if self._age is None: + return None + i = age_to_index(self._age) + return self._group_labels.AGES[i] + return None def _set_age(self, age): + if self._page is None: + if age != self._age: + self.age_changed_signal.emit(age) + else: + self._page.set_valid(True) self._age = age def update_color(self, color): self._color = color if self._age is not None: - self._buttons[self._age].xo_color = self._color + i = age_to_index(self._age) + self._pickers[i].set_color(self._color) def update_gender(self, gender): self._gender = gender - for i in range(8): - self._buttons[i].set_icon_name('%s-%d' % (self._gender, i)) - self._buttons[i].show() + + if self._gender in GENDERS: + gender_index = GENDERS.index(self._gender) + else: + gender_index = 0 + + for i in range(len(self._group_labels.AGES)): + self._pickers[i].set_icon( + self._group_labels.ICONS[i][gender_index]) diff --git a/src/jarabe/intro/colorpicker.py b/src/jarabe/intro/colorpicker.py index 0ec8c00b4b..ca152fc3b2 100644 --- a/src/jarabe/intro/colorpicker.py +++ b/src/jarabe/intro/colorpicker.py @@ -32,6 +32,7 @@ def __init__(self): self._set_random_colors() self.connect('button-press-event', self._button_press_cb) self.add(self._xo) + self._xo.show() def _button_press_cb(self, widget, event): if event.button == 1 and event.type == Gdk.EventType.BUTTON_PRESS: diff --git a/src/jarabe/intro/genderpicker.py b/src/jarabe/intro/genderpicker.py index 7df0e82674..3e8181e7cc 100644 --- a/src/jarabe/intro/genderpicker.py +++ b/src/jarabe/intro/genderpicker.py @@ -17,6 +17,8 @@ from gi.repository import Gtk from gi.repository import Gdk +from gi.repository import Gio +from gi.repository import GObject from sugar3.graphics.icon import EventIcon from sugar3.graphics import style @@ -26,13 +28,35 @@ GENDERS = ['female', 'male'] +def load_gender(): + settings = Gio.Settings('org.sugarlabs.user') + return settings.get_string('gender') + + +def save_gender(gender): + settings = Gio.Settings('org.sugarlabs.user') + if gender is not None: + settings.set_string('gender', gender) + else: + settings.set_string('gender', '') + + # DEPRECATED + from gi.repository import GConf + if gender is not None: + client = GConf.Client.get_default() + client.set_string('/desktop/sugar/user/gender', gender) + + class GenderPicker(Gtk.Grid): + + gender_changed_signal = GObject.Signal('gender-changed', arg_types=([str])) + def __init__(self): Gtk.Grid.__init__(self) self.set_row_spacing(style.DEFAULT_SPACING) self.set_column_spacing(style.DEFAULT_SPACING) - self._gender = None + self._gender = load_gender() self._buttons = [] self._nocolor = XoColor('#010101,#ffffff') self._color = XoColor() @@ -40,11 +64,23 @@ def __init__(self): for i, gender in enumerate(GENDERS): self._buttons.append(EventIcon(pixel_size=style.XLARGE_ICON_SIZE, icon_name='%s-6' % (gender))) - self._buttons[-1].show() self._buttons[-1].connect('button-press-event', self._button_press_cb, i) + self.attach(self._buttons[-1], i * 2, 0, 1, 1) + self._buttons[-1].show() + + self.reset_button = EventIcon(pixel_size=style.SMALL_ICON_SIZE, + icon_name='entry-cancel') + self.reset_button.connect('button-press-event', + self._reset_button_press_cb) + self.attach(self.reset_button, 1, 0, 1, 1) + self.reset_button.xo_color = XoColor('#010101,#a0a0a0') + self.reset_button.show() - self.attach(self._buttons[-1], i, 0, 1, 1) + def _reset_button_press_cb(self, widget, event): + self._set_gender('') + for i in range(len(GENDERS)): + self._buttons[i].xo_color = self._nocolor def _button_press_cb(self, widget, event, gender_index): if event.button == 1 and event.type == Gdk.EventType.BUTTON_PRESS: @@ -56,6 +92,7 @@ def get_gender(self): return self._gender def _set_gender(self, gender): + self.gender_changed_signal.emit(gender) self._gender = gender def update_color(self, color): diff --git a/src/jarabe/intro/window.py b/src/jarabe/intro/window.py index 72de64c490..36fb027513 100644 --- a/src/jarabe/intro/window.py +++ b/src/jarabe/intro/window.py @@ -39,21 +39,6 @@ from jarabe.intro import colorpicker from jarabe.intro import genderpicker -_SECONDS_PER_YEAR = 365 * 24 * 60 * 60. - - -def calculate_birth_timestamp(age): - age_in_seconds = age * _SECONDS_PER_YEAR - birth_timestamp = int(time.time() - age_in_seconds) - return birth_timestamp - - -def calculate_age(birth_timestamp): - age_in_seconds = time.time() - birth_timestamp - # Round to nearest int - age = int(math.floor(age_in_seconds / _SECONDS_PER_YEAR) + 0.5) - return age - def create_profile_with_nickname(nickname): user_profile = UserProfile() @@ -64,6 +49,11 @@ def create_profile_with_nickname(nickname): def create_profile(user_profile): settings = Gio.Settings('org.sugarlabs.user') + if user_profile.nickname in [None, '']: + nick = settings.get_string('nick') + if nick is not None: + logging.debug('recovering old nickname %s' % (nick)) + user_profile.nickname = nick settings.set_string('nick', user_profile.nickname) colors = user_profile.colors @@ -71,14 +61,9 @@ def create_profile(user_profile): colors = XoColor() settings.set_string('color', colors.to_string()) - if user_profile.gender is not None: - settings.set_string('gender', user_profile.gender) - else: - settings.set_string('gender', '') + genderpicker.save_gender(user_profile.gender) - settings.set_int('birth-timestamp', - calculate_birth_timestamp(user_profile.age)) - # settings.sync() + agepicker.save_age(user_profile.age) # DEPRECATED from gi.repository import GConf @@ -88,11 +73,6 @@ def create_profile(user_profile): client.set_string('/desktop/sugar/user/color', colors.to_string()) - if user_profile.gender is not None: - client.set_string('/desktop/sugar/user/gender', user_profile.gender) - - client.set_int('/desktop/sugar/user/birth_timestamp', - calculate_birth_timestamp(user_profile.age)) client.suggest_sync() if profile.get_pubkey() and profile.get_profile().privkey_hash: @@ -163,6 +143,7 @@ def __init__(self, intro): self._entry.set_size_request(style.zoom(300), -1) self._entry.set_max_length(45) grid.attach(self._entry, 0, 1, 1, 1) + self._entry.show() grid.show() alignment.show() @@ -253,11 +234,12 @@ def __init__(self, gender): grid.set_column_spacing(style.DEFAULT_SPACING) alignment.add(grid) - label = Gtk.Label(label=_('Select age:')) + self._ap = agepicker.AgePicker(gender, self) + + label = Gtk.Label(label=_(self._ap.get_label())) grid.attach(label, 0, 0, 1, 1) label.show() - self._ap = agepicker.AgePicker(gender) grid.attach(self._ap, 0, 1, 1, 1) self._ap.show() @@ -265,7 +247,6 @@ def __init__(self, gender): alignment.show() self._age = self._ap.get_age() - self.set_valid(True) def update_gender(self, gender): self._ap.update_gender(gender) @@ -288,7 +269,7 @@ class _IntroBox(Gtk.VBox): PAGE_FIRST = min(PAGE_NAME, PAGE_COLOR, PAGE_GENDER, PAGE_AGE) PAGE_LAST = max(PAGE_NAME, PAGE_COLOR, PAGE_GENDER, PAGE_AGE) - def __init__(self): + def __init__(self, start_on_age_page): Gtk.VBox.__init__(self) self.set_border_width(style.zoom(30)) @@ -310,6 +291,11 @@ def __init__(self): pwd_entry.pw_name) self._name_page.set_name(default_nick) + # XXX should also consider whether or not there is a nick + nick = settings.get_string('nick') + if start_on_age_page and nick: + self._page = self.PAGE_AGE + self._setup_page() def _setup_page(self): @@ -343,6 +329,7 @@ def _setup_age_page(self): setup_methods[self._page](self) self.pack_start(self._current_page, True, True, 0) + self._current_page.show() button_box = Gtk.HButtonBox() if self._page == self.PAGE_FIRST: @@ -354,6 +341,7 @@ def _setup_age_page(self): back_button.set_image(image) back_button.connect('clicked', self._back_activated_cb) button_box.pack_start(back_button, True, True, 0) + back_button.show() self._next_button = Gtk.Button() image = Icon(icon_name='go-right') @@ -370,12 +358,13 @@ def _setup_age_page(self): self._update_next_button() button_box.pack_start(self._next_button, True, True, 0) + self._next_button.show() self._current_page.connect('notify::valid', self._page_valid_changed_cb) self.pack_start(button_box, False, True, 0) - self.show_all() + button_box.show() def _update_next_button(self): self._next_button.set_sensitive(self._current_page.props.valid) @@ -420,7 +409,7 @@ def __init__(self): self.nickname = None self.colors = None self.gender = None - self.age = 12 + self.age = 0 class IntroWindow(Gtk.Window): @@ -430,13 +419,13 @@ class IntroWindow(Gtk.Window): 'done': (GObject.SignalFlags.RUN_FIRST, None, ([])), } - def __init__(self): + def __init__(self, start_on_age_page=False): Gtk.Window.__init__(self) self.props.decorated = False self.maximize() - self._intro_box = _IntroBox() + self._intro_box = _IntroBox(start_on_age_page) self._intro_box.connect('done', self._done_cb) self.add(self._intro_box) diff --git a/src/jarabe/main.py b/src/jarabe/main.py index 433b360c79..6fcbaaa518 100755 --- a/src/jarabe/main.py +++ b/src/jarabe/main.py @@ -352,10 +352,10 @@ def setup_theme(): Gtk.IconTheme.get_default().append_search_path(icons_path) -def _start_intro(): - window = IntroWindow() +def _start_intro(start_on_age_page=False): + window = IntroWindow(start_on_age_page=start_on_age_page) window.connect('done', __intro_window_done_cb) - window.show_all() + window.show() def _check_profile(): @@ -370,6 +370,10 @@ def _check_profile(): return False +def _check_group_label(): + return intro.check_group_label() + + def main(): # This can be removed once pygobject-3.10 is a requirement. # https://bugzilla.gnome.org/show_bug.cgi?id=686914 @@ -399,6 +403,8 @@ def main(): if not _check_profile(): _start_intro() + elif not _check_group_label(): + _start_intro(start_on_age_page=True) else: _begin_desktop_startup()