Back to index

gcompris  8.2.2
login.py
Go to the documentation of this file.
00001 #  gcompris - login
00002 #
00003 # Copyright (C) 2005 Bruno Coudoin
00004 #
00005 #   This program is free software; you can redistribute it and/or modify
00006 #   it under the terms of the GNU General Public License as published by
00007 #   the Free Software Foundation; either version 2 of the License, or
00008 #   (at your option) any later version.
00009 #
00010 #   This program is distributed in the hope that it will be useful,
00011 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 #   GNU General Public License for more details.
00014 #
00015 #   You should have received a copy of the GNU General Public License
00016 #   along with this program; if not, write to the Free Software
00017 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 #
00019 import gnomecanvas
00020 import gcompris
00021 import gcompris.utils
00022 import gcompris.skin
00023 import gcompris.admin
00024 import gtk
00025 import gtk.gdk
00026 import pango
00027 from gettext import gettext as _
00028 
00029 import math
00030 
00031 # Background screens
00032 backgrounds = [
00033   "images/scenery2_background.png",
00034   "images/scenery3_background.png",
00035   "images/scenery4_background.png",
00036   "images/scenery5_background.png",
00037   "images/scenery6_background.png"
00038 ]
00039 
00040 MAX_USERS_AT_ONCE = 10
00041 
00042 class Gcompris_login:
00043   """Login screen for gcompris"""
00044 
00045 
00046   def __init__(self, gcomprisBoard):
00047     self.gcomprisBoard = gcomprisBoard
00048 
00049     self.gcomprisBoard.disable_im_context = True
00050 
00051     print("Gcompris_login __init__.")
00052 
00053 
00054   def start(self):
00055     self.gcomprisBoard.level=1
00056     self.gcomprisBoard.maxlevel=1
00057     self.gcomprisBoard.sublevel=1
00058     self.gcomprisBoard.number_of_sublevel=1
00059     pixmap = gcompris.utils.load_pixmap(gcompris.skin.image_to_skin("button_reload.png"))
00060     if(pixmap):
00061       gcompris.bar_set_repeat_icon(pixmap)
00062       gcompris.bar_set(gcompris.BAR_REPEAT_ICON)
00063     else:
00064       gcompris.bar_set(gcompris.BAR_REPEAT)
00065 
00066     gcompris.bar_set_level(self.gcomprisBoard)
00067 
00068     gcompris.set_background(self.gcomprisBoard.canvas.root(),
00069                             backgrounds[self.gcomprisBoard.level-1])
00070 
00071     # Get the default profile
00072     self.Prop = gcompris.get_properties()
00073 
00074     # init config to default values
00075     self.config_dict = self.init_config()
00076 
00077     print gcompris.get_board_conf(), self.gcomprisBoard.board_id, self.gcomprisBoard.name
00078 
00079     # change configured values
00080     self.config_dict.update(gcompris.get_board_conf())
00081 
00082     # Create and Initialize the rootitem.
00083     self.init_rootitem(self.Prop)
00084 
00085     # Get the user list
00086     users = []
00087     for group_id in self.Prop.profile.group_ids:
00088       users.extend( gcompris.admin.get_users_from_group(group_id))
00089 
00090     self.users = self.check_unique_id(users)
00091 
00092     if eval(self.config_dict['entry_text']):
00093       self.entry_text()
00094     else:
00095       self.display_user_by_letter(self.users, "")
00096 
00097     print("Gcompris_login start.")
00098 
00099 
00100   def init_rootitem(self, Prop):
00101     print "__rootitem__"
00102     # Create our rootitem.
00103     # We put each canvas item in it so at the end we only have to kill it.
00104     # The canvas deletes all the items it contains automaticaly.
00105     self.rootitem = self.gcomprisBoard.canvas.root().add(
00106       gnomecanvas.CanvasGroup,
00107       x=0.0,
00108       y=0.0
00109       )
00110 
00111     # Display the profile name
00112     x = gcompris.BOARD_WIDTH-100
00113     y = 20.0
00114     text = _("Profile: ") + Prop.profile.name
00115 
00116     # Shadow
00117     self.rootitem.add(
00118       gnomecanvas.CanvasText,
00119       x= x + 1,
00120       y= y + 1,
00121       text= text,
00122       fill_color="black",
00123       font=gcompris.skin.get_font("gcompris/board/small"),
00124       justification=gtk.JUSTIFY_RIGHT
00125       )
00126 
00127     # Profile name
00128     self.rootitem.add(
00129       gnomecanvas.CanvasText,
00130       x= x,
00131       y= y,
00132       text= text,
00133       fill_color="white",
00134       font=gcompris.skin.get_font("gcompris/board/small"),
00135       justification=gtk.JUSTIFY_RIGHT
00136       )
00137 
00138 
00139   def check_unique_id(self, users):
00140     passed = {}
00141     for user in users:
00142       passed[user.login] = user
00143 
00144     result = []
00145     keys = passed.keys()
00146     keys.sort()
00147     for login in keys:
00148       result.append(passed[login])
00149 
00150     return result
00151 
00152   def end(self):
00153 
00154     # Remove the root item removes all the others inside it
00155     self.rootitem.destroy()
00156 
00157 
00158   def ok(self):
00159     print("Gcompris_login ok.")
00160 
00161 
00162   def repeat(self):
00163     print("Gcompris_login repeat.")
00164     self.rootitem.destroy()
00165 
00166     self.init_rootitem(self.Prop)
00167 
00168     if eval(self.config_dict['entry_text']):
00169       self.entry_text()
00170     else:
00171       self.display_user_by_letter(self.users, "")
00172 
00173   def config(self):
00174     print("Gcompris_login config.")
00175 
00176 
00177   def key_press(self, keyval, commit_str, preedit_str):
00178     print("Gcompris_login key press. %i" % keyval)
00179 
00180     # Return  True  if you did process a key
00181     # Return  False if you did not processed a key
00182     #         (gtk need to send it to next widget)
00183     return False
00184 
00185   def pause(self, pause):
00186     print("Gcompris_login pause. %i" % pause)
00187     # There is a problem with GTK widgets, they are not covered by the help
00188     # We hide/show them here
00189     if(pause):
00190       self.entry.hide()
00191     else:
00192       self.entryt.show()
00193 
00194 
00195   def set_level(self, level):
00196     print("Gcompris_login set level. %i" % level)
00197 
00198   # -------------------------------
00199   # ---- End of Initialisation ----
00200   # -------------------------------
00201 
00202   # Display user by letter
00203   # The first letter of the users is displayed
00204   # If the remaining list of users with this letter is
00205   # too large, then the next letter is proposed.
00206   # Once the user list is not too long, it is displayed
00207   #
00208   # param: users is the sorted list of users to display
00209   # param: start_filter is a string filter to apply on
00210   #        the first letters of the user name
00211   #
00212   def display_user_by_letter(self, users, start_filter):
00213 
00214     print "display_user_by_letter start_filter=" + start_filter
00215 
00216     first_letters = []
00217     current_letter = None
00218     remaining_users=0
00219 
00220     for user in users:
00221       if eval(self.config_dict['uppercase_only']):
00222         login = user.login.decode('utf8').upper().encode('utf8')
00223       else:
00224         login = user.login
00225       if login.startswith(start_filter):
00226         remaining_users += 1
00227         if(len(start_filter)<len(login)):
00228           if(not current_letter or
00229              current_letter != login[len(start_filter)]):
00230             current_letter = login[len(start_filter)]
00231             first_letters.append(current_letter)
00232 
00233     # Fine we have the list of first letters
00234     if(remaining_users<MAX_USERS_AT_ONCE):
00235       # We now can display the list of users
00236       self.display_user_list(users, start_filter)
00237     else:
00238       # Display only the letters
00239       self.display_letters(first_letters, users, start_filter)
00240 
00241   #
00242   # Display the letters in 'letters'
00243   #
00244   # param users and start_filter are just need to let
00245   # this function pass it to it's event function
00246   #
00247   def display_letters(self, letters, users, start_filter):
00248 
00249     # Create a group for the letters
00250     self.letter_rootitem = self.rootitem.add(
00251       self.rootitem,
00252       x=0.0,
00253       y=0.0
00254       )
00255 
00256     #
00257     # Display the current filter
00258     #
00259 
00260     x = gcompris.BOARD_WIDTH/2
00261     y = 20
00262 
00263     # The shadow
00264     self.letter_rootitem.add(
00265       gnomecanvas.CanvasText,
00266       x= x + 1.5,
00267       y= y + 1.5,
00268       text= _("Login: ") + start_filter + "...",
00269       fill_color="black",
00270       font=gcompris.skin.get_font("gcompris/board/huge"),
00271       )
00272     # The text
00273     self.letter_rootitem.add(
00274       gnomecanvas.CanvasText,
00275       x= x,
00276       y= y,
00277       text= _("Login: ") + start_filter + "...",
00278       fill_color="white",
00279       font=gcompris.skin.get_font("gcompris/board/huge"),
00280       )
00281 
00282 
00283     # Tricky but does the job, try to make the layout as large as
00284     # possible
00285     step_x = 480/math.sqrt(len(letters))
00286 
00287     start_x = 100
00288     x = start_x
00289     y = 100
00290     i = 0
00291     step_y = step_x
00292     current_line = 0
00293     max_letter_by_line = (gcompris.BOARD_WIDTH-start_x*2)/step_x
00294     letter_by_line = max_letter_by_line
00295     button_pixbuf = gcompris.utils.load_pixmap(gcompris.skin.image_to_skin("ok.png"))
00296 
00297     for letter in letters:
00298 
00299       # Display both cases for the letter
00300       if eval(self.config_dict['uppercase_only']):
00301         text = letter
00302       else:
00303         text = letter.upper() + letter.lower()
00304 
00305       item = self.letter_rootitem.add(
00306         gnomecanvas.CanvasPixbuf,
00307         pixbuf = button_pixbuf,
00308         x = x -  button_pixbuf.get_width()/2,
00309         y = y -  button_pixbuf.get_height()/2,
00310         )
00311       # This item is clickeable and it must be seen
00312       item.connect("event", gcompris.utils.item_event_focus)
00313       item.connect("event", self.letter_click_event,
00314                    (users, start_filter + letter))
00315 
00316       # The shadow
00317       item = self.letter_rootitem.add(
00318         gnomecanvas.CanvasText,
00319         x= x + 1.5,
00320         y= y + 1.5,
00321         text= text,
00322         fill_color="black",
00323         font=gcompris.skin.get_font("gcompris/board/huge"),
00324         )
00325       item.connect("event", self.letter_click_event,
00326                    (users, start_filter + letter))
00327 
00328       # The text
00329       item = self.letter_rootitem.add(
00330         gnomecanvas.CanvasText,
00331         x= x,
00332         y= y,
00333         text= text,
00334         fill_color="white",
00335         font=gcompris.skin.get_font("gcompris/board/huge"),
00336         )
00337       item.connect("event", self.letter_click_event,
00338                    (users, start_filter + letter))
00339       x += step_x
00340 
00341       i += 1
00342 
00343       # Perform the column switch
00344       if(i>letter_by_line):
00345         i = 0
00346         if(current_line%2):
00347           x = start_x
00348           letter_by_line = max_letter_by_line
00349         else:
00350           x = start_x + step_x/2
00351           letter_by_line = max_letter_by_line-1
00352 
00353         y += step_y
00354         current_line += 1
00355 
00356 
00357   # Display the user list so the user can click on it's name
00358   #
00359   # param users is the list of users to display
00360   #
00361   def display_user_list(self, users, start_filter):
00362 
00363     y_start = 80
00364     y = y_start
00365     x = gcompris.BOARD_WIDTH/4
00366     i = 0
00367     step_y = 90
00368     button_pixbuf = gcompris.utils.load_pixmap(gcompris.skin.image_to_skin("button_large2.png"))
00369 
00370     for user in users:
00371       if eval(self.config_dict['uppercase_only']):
00372         login = user.login.decode('utf8').upper().encode('utf8')
00373       else:
00374         login = user.login
00375 
00376       if not login.startswith(start_filter):
00377         continue
00378 
00379       item = self.rootitem.add(
00380         gnomecanvas.CanvasPixbuf,
00381         pixbuf = button_pixbuf,
00382         x = x -  button_pixbuf.get_width()/2,
00383         y = y -  button_pixbuf.get_height()/2,
00384         )
00385       # This item is clickeable and it must be seen
00386       item.connect("event", gcompris.utils.item_event_focus)
00387       item.connect("event", self.name_click_event, user)
00388 
00389 
00390       # The shadow
00391       item = self.rootitem.add(
00392         gnomecanvas.CanvasText,
00393         x= x + 1.5,
00394         y= y + 1.5,
00395         text= login,
00396         fill_color="black",
00397         font=gcompris.skin.get_font("gcompris/board/huge"),
00398         )
00399       item.connect("event", self.name_click_event, user)
00400 
00401       # The text
00402       item = self.rootitem.add(
00403         gnomecanvas.CanvasText,
00404         x= x,
00405         y= y,
00406         text= login,
00407         fill_color="white",
00408         font=gcompris.skin.get_font("gcompris/board/huge"),
00409         )
00410       item.connect("event", self.name_click_event, user)
00411 
00412       y += step_y
00413       i += 1
00414 
00415       # Perform the column switch
00416       if(i==5):
00417         y = y_start
00418         x = 3*gcompris.BOARD_WIDTH/4
00419 
00420 
00421   #
00422   # Event when a click happen on a letter
00423   # data[0] is the user list we work on
00424   # data[1] is the start filter
00425   def letter_click_event(self, widget, event, data):
00426     if event.type == gtk.gdk.BUTTON_PRESS:
00427       self.letter_rootitem.destroy()
00428       self.display_user_by_letter(data[0], data[1])
00429       return True
00430 
00431     return False
00432 
00433   #
00434   # Event when a click happen on a user name
00435   #
00436   def name_click_event(self, widget, event, user):
00437     if event.type == gtk.gdk.BUTTON_PRESS:
00438       print "selected user = " + user.login
00439 
00440       self.logon(user)
00441       return True
00442 
00443     return False
00444 
00445   def logon(self, user):
00446     gcompris.admin.set_current_user(user)
00447     gcompris.admin.board_run_next(self.Prop.menu_board)
00448 
00449 
00450   def init_config(self):
00451     default_config = { 'uppercase_only'    : 'False',
00452                        'entry_text'      : 'False'
00453                        }
00454     return default_config
00455 
00456 
00457   def entry_text(self):
00458     print "__entry__"
00459     self.entry = gtk.Entry()
00460 
00461     self.entry.modify_font(pango.FontDescription("sans bold 36"))
00462     text_color = gtk.gdk.color_parse("brown")
00463     text_color_selected = gtk.gdk.color_parse("brown")
00464     bg_color = gtk.gdk.color_parse("blue")
00465 
00466     self.entry.modify_text(gtk.STATE_NORMAL, text_color)
00467     self.entry.modify_text(gtk.STATE_SELECTED, text_color_selected)
00468     self.entry.modify_base(gtk.STATE_NORMAL, bg_color)
00469 
00470     self.entry.set_max_length(50)
00471     self.entry.connect("activate", self.enter_callback)
00472     self.entry.connect("changed", self.enter_char_callback)
00473 
00474     self.entry.show()
00475 
00476     self.widget = self.rootitem.add(
00477       gnomecanvas.CanvasWidget,
00478       widget=self.entry,
00479       x=400,
00480       y=400,
00481       width=400,
00482       height=72,
00483       anchor=gtk.ANCHOR_CENTER,
00484       size_pixels=False
00485       )
00486 
00487     self.widget.raise_to_top()
00488 
00489     # does not work. Why ?
00490     #self.gcomprisBoard.canvas.grab_focus()
00491     self.widget.grab_focus()
00492     self.entry.grab_focus()
00493 
00494   def enter_char_callback(self, widget):
00495     if eval(self.config_dict['uppercase_only']):
00496       text = widget.get_text()
00497       widget.set_text(text.decode('utf8').upper().encode('utf8'))
00498 
00499   def enter_callback(self, widget):
00500     text = widget.get_text()
00501 
00502     found = False
00503     for user in self.users:
00504       if eval(self.config_dict['uppercase_only']):
00505         login = user.login.decode('utf8').upper().encode('utf8')
00506       else:
00507         login = user.login
00508       if text == login:
00509         self.widget.destroy()
00510         self.logon(user)
00511         found = True
00512 
00513     if not found:
00514       widget.set_text('')
00515 
00516   def config_start(self, profile):
00517     print '__login config__'
00518     # keep profile in mind
00519     self.configuring_profile = profile
00520 
00521     # init with default values
00522     self.config_dict = self.init_config()
00523 
00524     #get the configured values for that profile
00525     self.config_dict.update(gcompris.get_conf(profile, self.gcomprisBoard))
00526 
00527     # Init configuration window:
00528     # all the configuration functions will use it
00529     # all the configuration functions returns values for their key in
00530     # the dict passed to the apply_callback
00531     # the returned value is the main GtkVBox of the window,
00532     #we can add what you want in it.
00533 
00534     self.main_vbox = gcompris.configuration_window ( \
00535       _('<b>%s</b> configuration\n for profile <b>%s</b>') % ('Login', profile.name ),
00536       self.ok_callback
00537       )
00538 
00539     # toggle box
00540     uppercase = gcompris.boolean_box(_('Uppercase only text'),
00541                                         'uppercase_only',
00542                                         eval(self.config_dict['uppercase_only'])
00543                                         )
00544 
00545     #uppercase.set_sensitive(False)
00546 
00547     gcompris.separator()
00548 
00549     # toggle box
00550     entry_text = gcompris.boolean_box(_('Enter login to log in'),
00551                                         'entry_text',
00552                                         eval(self.config_dict['entry_text'])
00553                                         )
00554 
00555 
00556   def config_stop(self):
00557     pass
00558 
00559   def ok_callback(self, table):
00560     if(not table):
00561       return
00562     for key,value in table.iteritems():
00563       gcompris.set_board_conf(self.configuring_profile, self.gcomprisBoard, key, value)
00564