# gcompris - login
#
# Copyright (C) 2005, 2008 Bruno Coudoin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
#
import goocanvas
import gcompris
import gcompris.utils
import gcompris.skin
import gcompris.admin
import gtk
import gtk.gdk
import pango
from gcompris import gcompris_gettext as _
import math
# Background screens
backgrounds = [
"login/scenery2_background.png",
"login/scenery3_background.png",
"login/scenery4_background.png",
"login/scenery5_background.png",
"login/scenery6_background.png"
]
MAX_USERS_AT_ONCE = 10
class Gcompris_login:
"""Login screen for gcompris"""
def __init__(self, gcomprisBoard):
self.gcomprisBoard = gcomprisBoard
self.gcomprisBoard.disable_im_context = True
self.entry = []
def start(self):
self.gcomprisBoard.level=1
self.gcomprisBoard.maxlevel=1
self.gcomprisBoard.sublevel=1
self.gcomprisBoard.number_of_sublevel=1
gcompris.bar_set(gcompris.BAR_REPEAT|gcompris.BAR_CONFIG)
gcompris.bar_set_level(self.gcomprisBoard)
gcompris.set_background(self.gcomprisBoard.canvas.get_root_item(),
backgrounds[self.gcomprisBoard.level-1])
# Get the default profile
self.Prop = gcompris.get_properties()
if not self.Prop:
return
# init config to default values
self.config_dict = self.init_config()
# change configured values
self.config_dict.update(gcompris.get_board_conf())
# Create and Initialize the rootitem.
self.init_rootitem(self.Prop)
# Get the user list
users = []
if self.Prop.profile:
for group_id in self.Prop.profile.group_ids:
users.extend( gcompris.admin.get_users_from_group(group_id))
self.users = self.check_unique_id(users)
if eval(self.config_dict['entry_text']):
self.entry_text()
else:
self.display_user_by_letter(self.users, "")
def init_rootitem(self, Prop):
# Create our rootitem.
# We put each canvas item in it so at the end we only have to kill it.
# The canvas deletes all the items it contains automaticaly.
self.rootitem = goocanvas.Group(parent = self.gcomprisBoard.canvas.get_root_item())
# Display the profile name
x = gcompris.BOARD_WIDTH-100
y = 20.0
text = _("Profile: ") + (Prop.profile.name if Prop.profile else "")
# Profile name
goocanvas.Text(
parent = self.rootitem,
x= x,
y= y,
text= text,
fill_color="white",
font=gcompris.skin.get_font("gcompris/board/small"),
anchor = gtk.ANCHOR_CENTER
)
def check_unique_id(self, users):
passed = {}
for user in users:
passed[user.login] = user
result = []
keys = passed.keys()
keys.sort()
for login in keys:
result.append(passed[login])
return result
def end(self):
# Remove the root item removes all the others inside it
self.rootitem.remove()
def ok(self):
pass
def repeat(self):
self.rootitem.remove()
self.init_rootitem(self.Prop)
if eval(self.config_dict['entry_text']):
self.entry_text()
else:
self.display_user_by_letter(self.users, "")
def config(self):
pass
def key_press(self, keyval, commit_str, preedit_str):
# Return True if you did process a key
# Return False if you did not processed a key
# (gtk need to send it to next widget)
return False
def pause(self, pause):
# There is a problem with GTK widgets, they are not covered by the help
# We hide/show them here
if(pause):
if self.entry: self.widget.props.visibility = goocanvas.ITEM_INVISIBLE
else:
if self.entry: self.widget.props.visibility = goocanvas.ITEM_VISIBLE
def set_level(self, level):
pass
# -------------------------------
# ---- End of Initialisation ----
# -------------------------------
# Display user by letter
# The first letter of the users is displayed
# If the remaining list of users with this letter is
# too large, then the next letter is proposed.
# Once the user list is not too long, it is displayed
#
# param: users is the sorted list of users to display
# param: start_filter is a string filter to apply on
# the first letters of the user name
#
def display_user_by_letter(self, users, start_filter):
first_letters = []
current_letter = None
remaining_users=0
for user in users:
if eval(self.config_dict['uppercase_only']):
login = user.login.decode('utf8').upper().encode('utf8')
else:
login = user.login
if login.startswith(start_filter):
remaining_users += 1
if(len(start_filter)letter_by_line):
i = 0
if(current_line%2):
x = start_x
letter_by_line = max_letter_by_line
else:
x = start_x + step_x/2
letter_by_line = max_letter_by_line-1
y += step_y
current_line += 1
# Display the user list so the user can click on it's name
#
# param users is the list of users to display
#
def display_user_list(self, users, start_filter):
y_start = 80
y = y_start
x = gcompris.BOARD_WIDTH/4
i = 0
step_y = 90
for user in users:
if eval(self.config_dict['uppercase_only']):
login = user.login.decode('utf8').upper().encode('utf8')
else:
login = user.login
if not login.startswith(start_filter):
continue
# The text
item = goocanvas.Text(
parent = self.rootitem,
x= x,
y= y,
text= login,
fill_color="white",
font=gcompris.skin.get_font("gcompris/board/huge"),
anchor = gtk.ANCHOR_CENTER,
)
item.connect("button_press_event", self.name_click_event, user)
gap = 10
bounds = item.get_bounds()
item_bg = \
goocanvas.Rect(
parent = self.rootitem,
x = bounds.x1 - gap,
y = bounds.y1 - gap,
width = bounds.x2 - bounds.x1 + gap*2,
height = bounds.y2 - bounds.y1 + gap*2,
line_width=2.0,
fill_color_rgba=0x555555CAL,
stroke_color_rgba=0xFFFFFFFFL,
radius_x=5.0,
radius_y=5.0)
item_bg.connect("button_press_event", self.name_click_event, user)
item.raise_(item_bg)
# This item is clickeable and it must be seen
gcompris.utils.item_focus_init(item, item_bg)
gcompris.utils.item_focus_init(item_bg, None)
y += step_y
i += 1
# Perform the column switch
if(i==5):
y = y_start
x = 3*gcompris.BOARD_WIDTH/4
#
# Event when a click happen on a letter
# data[0] is the user list we work on
# data[1] is the start filter
def letter_click_event(self, widget, target, event, data):
if event.type == gtk.gdk.BUTTON_PRESS:
self.letter_rootitem.remove()
self.display_user_by_letter(data[0], data[1])
return True
return False
#
# Event when a click happen on a user name
#
def name_click_event(self, widget, target, event, user):
if event.type == gtk.gdk.BUTTON_PRESS:
self.logon(user)
return True
return False
def logon(self, user):
gcompris.admin.set_current_user(user)
gcompris.admin.board_run_next(self.Prop.menu_board)
def init_config(self):
default_config = { 'uppercase_only' : 'False',
'entry_text' : 'False'
}
return default_config
def entry_text(self):
self.entry = gtk.Entry()
self.entry.modify_font(pango.FontDescription("sans bold 36"))
text_color = gtk.gdk.color_parse("black")
text_color_selected = gtk.gdk.color_parse("black")
bg_color = gtk.gdk.color_parse("white")
self.entry.modify_text(gtk.STATE_NORMAL, text_color)
self.entry.modify_text(gtk.STATE_SELECTED, text_color_selected)
self.entry.modify_base(gtk.STATE_NORMAL, bg_color)
self.entry.set_max_length(50)
self.entry.connect("activate", self.enter_callback)
self.entry.connect("changed", self.enter_char_callback)
self.widget = goocanvas.Widget(
parent = self.rootitem,
widget=self.entry,
x=400,
y=400,
width=400,
height=72,
anchor=gtk.ANCHOR_CENTER,
)
self.widget.raise_(None)
self.entry.grab_focus()
def enter_char_callback(self, widget):
if eval(self.config_dict['uppercase_only']):
text = widget.get_text()
widget.set_text(text.decode('utf8').upper().encode('utf8'))
def enter_callback(self, widget):
text = widget.get_text()
found = False
for user in self.users:
if eval(self.config_dict['uppercase_only']):
login = user.login.decode('utf8').upper().encode('utf8')
else:
login = user.login
if text == login:
self.widget.remove()
self.logon(user)
found = True
if not found:
widget.set_text('')
def config_start(self, profile):
# keep profile in mind
self.configuring_profile = profile
# init with default values
self.config_dict = self.init_config()
# get the configured values for that profile
self.config_dict.update(gcompris.get_conf(profile, self.gcomprisBoard))
# Init configuration window:
# all the configuration functions will use it
# all the configuration functions returns values for their key in
# the dict passed to the apply_callback
# the returned value is the main GtkVBox of the window,
#we can add what you want in it.
bconf = gcompris.configuration_window ( \
_('%s configuration\n for profile %s')
% ('Login', ( profile.name if profile else "" ) ),
self.ok_callback
)
# toggle box
uppercase = gcompris.boolean_box(bconf, _('Uppercase only text'),
'uppercase_only',
eval(self.config_dict['uppercase_only'])
)
#uppercase.set_sensitive(False)
gcompris.separator(bconf)
# toggle box
entry_text = gcompris.boolean_box(bconf, _('Enter login to log in'),
'entry_text',
eval(self.config_dict['entry_text'])
)
def config_stop(self):
pass
def ok_callback(self, table):
if(not table):
return True
for key,value in table.iteritems():
gcompris.set_board_conf(self.configuring_profile, self.gcomprisBoard, key, value)
return True