Back to index

gcompris  8.2.2
class_edit.py
Go to the documentation of this file.
00001 #  gcompris - class_edit.py
00002 # 
00003 # Copyright (C) 2005 Bruno Coudoin and Yves Combe
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 
00020 
00021 import gtk
00022 import gobject
00023 from gettext import gettext as _
00024 
00025 # Database
00026 from pysqlite2 import dbapi2 as sqlite
00027 
00028 import user_list
00029 
00030 import constants
00031 
00032 # User List Management
00033 (
00034   COLUMN_USERID,
00035   COLUMN_FIRSTNAME,
00036   COLUMN_LASTNAME,
00037   COLUMN_USER_EDITABLE
00038 ) = range(4)
00039 
00040 
00041 class ClassEdit(gtk.Window):
00042 
00043     def __init__(self, db_connect, db_cursor,
00044                  class_id, class_name, teacher_name,
00045                  list_class):
00046         # Create the toplevel window
00047         gtk.Window.__init__(self)
00048 
00049         self.cur = db_cursor
00050         self.con = db_connect
00051 
00052         self.class_id = class_id
00053         self.class_name = class_name
00054         self.teacher_name = teacher_name
00055         
00056         # A pointer to the user_list class
00057         # Will be called to refresh the list when edit is done
00058         self.list_class = list_class
00059         
00060         self.set_title(_("Editing a Class"))
00061         self.set_border_width(8)
00062         self.set_default_size(320, 350)
00063 
00064         if(self.class_name):
00065             frame = gtk.Frame(_("Editing class: ") + self.class_name)
00066             self.new_class = False
00067         else:
00068             frame = gtk.Frame(_("Editing a new class"))
00069             self.new_class = True
00070             
00071         # Connect the "destroy" event to close
00072         # FIXME: This makes the close code beeing called twice
00073         #        because the close destroy also call close again.
00074         frame.connect("destroy", self.close)
00075         
00076         self.add(frame)
00077 
00078         # Main VBOX
00079         vbox = gtk.VBox(False, 8)
00080         vbox.set_border_width(8)
00081         frame.add(vbox)
00082 
00083         # Label and Entry for the class name
00084         table = gtk.Table(2, 2, homogeneous=False)
00085         table.set_border_width(0)
00086         table.set_row_spacings(0)
00087         table.set_col_spacings(20)
00088         vbox.pack_start(table, True, True, 0)
00089         
00090         label = gtk.Label(_('Class:'))
00091         label.set_alignment(0, 0)
00092         table.attach(label, 0, 1, 0, 1, xoptions=gtk.SHRINK,
00093                      yoptions=gtk.EXPAND)
00094         self.entry_class = gtk.Entry()
00095         self.entry_class.set_max_length(20)
00096         self.entry_class.insert_text(self.class_name, position=0)
00097         table.attach(self.entry_class, 1, 2, 0, 1,
00098                      xoptions=gtk.SHRINK, yoptions=gtk.EXPAND)
00099 
00100         # FIXME: How to remove the default selection
00101         
00102         # Label and Entry for the teacher name
00103         label = gtk.Label(_('Teacher:'))
00104         label.set_alignment(0, 0)
00105         table.attach(label, 0, 1, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.EXPAND)
00106         self.entry_teacher = gtk.Entry()
00107         self.entry_teacher.set_max_length(30)
00108         self.entry_teacher.insert_text(self.teacher_name, position=0)
00109         table.attach(self.entry_teacher, 1, 2, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.EXPAND)
00110 
00111         # Top message gives instructions
00112         vbox.pack_start(gtk.HSeparator(), False, False, 0)
00113         label = gtk.Label(_('Assign all the users belonging to this class'))
00114         vbox.pack_start(label, False, False, 0)
00115         vbox.pack_start(gtk.HSeparator(), False, False, 0)
00116 
00117         # Lower area
00118         hbox = gtk.HBox(False, 8)
00119         vbox.pack_start(hbox, True, True, 0)
00120 
00121         # Left list
00122         # ---------
00123 
00124         # Create the table
00125         sw = gtk.ScrolledWindow()
00126         sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
00127         sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
00128 
00129         # create tree model
00130         self.model_left = self.__create_model(False, class_id)
00131 
00132         # create tree view
00133         treeview = gtk.TreeView(self.model_left)
00134         treeview.set_rules_hint(True)
00135         treeview.set_search_column(COLUMN_FIRSTNAME)
00136         treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
00137 
00138         sw.add(treeview)
00139         
00140         # add columns to the tree view
00141         self.__add_columns(treeview)
00142 
00143         hbox.pack_start(sw, True, True, 0)
00144 
00145 
00146         # Middle Button
00147         # -------------
00148         vbox2 = gtk.VBox(False, 8)
00149         vbox2.set_border_width(8)
00150         hbox.pack_start(vbox2, True, True, 0)
00151 
00152         button_add = gtk.Button(stock='gtk-add')
00153         button_add.connect("clicked", self.add_user, treeview)
00154         vbox2.pack_start(button_add, False, False, 0)
00155 
00156         button_delete = gtk.Button(stock='gtk-remove')
00157         vbox2.pack_start(button_delete, False, False, 0)
00158 
00159         # Right List
00160         # ----------
00161 
00162         # Create the table
00163         sw2 = gtk.ScrolledWindow()
00164         sw2.set_shadow_type(gtk.SHADOW_ETCHED_IN)
00165         sw2.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
00166 
00167         # create tree model
00168         self.model_right = self.__create_model(True, class_id)
00169 
00170         # create tree view
00171         treeview2 = gtk.TreeView(self.model_right)
00172         treeview2.set_rules_hint(True)
00173         treeview2.set_search_column(COLUMN_FIRSTNAME)
00174         treeview2.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
00175 
00176         sw2.add(treeview2)
00177         
00178         # add columns to the tree view
00179         self.__add_columns(treeview2)
00180 
00181         hbox.pack_start(sw2, True, True, 0)
00182 
00183         # Confirmation Buttons
00184         # --------------------
00185         vbox.pack_start(gtk.HSeparator(), False, False, 0)
00186 
00187         bbox = gtk.HBox(homogeneous=False, spacing=8)
00188         
00189         button = gtk.Button(stock='gtk-help')
00190         bbox.pack_start(button, expand=False, fill=False, padding=0)
00191 
00192         button = gtk.Button(stock='gtk-ok')
00193         bbox.pack_end(button, expand=False, fill=False, padding=0)
00194         button.connect("clicked", self.ok)
00195 
00196         button = gtk.Button(stock='gtk-close')
00197         bbox.pack_end(button, expand=False, fill=False, padding=0)
00198         button.connect("clicked", self.close)
00199 
00200         vbox.pack_start(bbox, False, False, 0)
00201         
00202         # Missing callbacks
00203         button_delete.connect("clicked", self.remove_user, treeview2)
00204 
00205         # Ready GO
00206         self.show_all()
00207 
00208 
00209     # -------------------
00210     # User Management
00211     # -------------------
00212 
00213     # Add user in the model
00214     def add_user_in_model(self, model, user):
00215         iter = model.append()
00216         model.set (iter,
00217                    COLUMN_USERID,    user[COLUMN_USERID],
00218                    COLUMN_FIRSTNAME, user[COLUMN_FIRSTNAME],
00219                    COLUMN_LASTNAME,  user[COLUMN_LASTNAME],
00220                    COLUMN_USER_EDITABLE,  False
00221                    )
00222 
00223     # If class_id is provided, only users in this class are inserted
00224     # If with = True, create a list only with the given class_id.
00225     #           False, create a list only without the given class_id
00226     def __create_model(self, with, class_id):
00227 
00228         # Grab the user data
00229         if(with):
00230             self.cur.execute('SELECT user_id,firstname,lastname FROM users where class_id=? ORDER BY login', (class_id,))
00231         else:
00232             self.cur.execute('SELECT user_id,firstname,lastname FROM users WHERE class_id!=? ORDER BY login', (class_id,))
00233         user_data = self.cur.fetchall()
00234 
00235         model = gtk.ListStore(
00236             gobject.TYPE_INT,
00237             gobject.TYPE_STRING,
00238             gobject.TYPE_STRING,
00239             gobject.TYPE_BOOLEAN)
00240 
00241         for user in user_data:
00242             self.add_user_in_model(model, user)
00243 
00244         return model
00245 
00246     def __add_columns(self, treeview):
00247 
00248         model = treeview.get_model()
00249 
00250         # columns for first name
00251         renderer = gtk.CellRendererText()
00252         renderer.set_data("column", COLUMN_FIRSTNAME)
00253         column = gtk.TreeViewColumn(_('First Name'), renderer,
00254                                     text=COLUMN_FIRSTNAME,
00255                                     editable=COLUMN_USER_EDITABLE)
00256         column.set_sort_column_id(COLUMN_FIRSTNAME)
00257         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00258         column.set_fixed_width(constants.COLUMN_WIDTH_FIRSTNAME)
00259         treeview.append_column(column)
00260 
00261         # column for last name
00262         renderer = gtk.CellRendererText()
00263         renderer.set_data("column", COLUMN_LASTNAME)
00264         column = gtk.TreeViewColumn(_('Last Name'), renderer,
00265                                     text=COLUMN_LASTNAME,
00266                                     editable=COLUMN_USER_EDITABLE)
00267         column.set_sort_column_id(COLUMN_LASTNAME)
00268         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00269         column.set_fixed_width(constants.COLUMN_WIDTH_LASTNAME)
00270         treeview.append_column(column)
00271 
00272 
00273     # Add a user from the left list to the right list
00274     #
00275     def add_user(self, button, treeview):
00276         model = treeview.get_model()
00277         treestore, paths = treeview.get_selection().get_selected_rows()
00278         paths.reverse()
00279 
00280         if(len(paths)>0 and self.new_class):
00281             self.create_class()
00282 
00283         for path in paths:
00284             iter = treestore.get_iter(path)
00285             path = model.get_path(iter)[0]
00286             user_id        = model.get_value(iter, COLUMN_USERID)
00287             user_firstname = model.get_value(iter, COLUMN_FIRSTNAME)
00288             user_lastname  = model.get_value(iter, COLUMN_LASTNAME)
00289             model.remove(iter)
00290 
00291             # Add in the the right view
00292             self.add_user_in_model(self.model_right, (user_id, user_firstname, user_lastname))
00293             
00294             # Save the change in the base
00295             self.cur.execute('UPDATE users SET class_id=? WHERE user_id=?',
00296                              (self.class_id, user_id))
00297             self.con.commit()
00298             print "UPDATE users SET class_id=%d" %self.class_id
00299 
00300     # Remove a user from the right list to the left list
00301     #
00302     def remove_user(self, button, treeview):
00303         model = treeview.get_model()
00304         treestore, paths = treeview.get_selection().get_selected_rows()
00305         paths.reverse()
00306         
00307         for path in paths:
00308             iter = treestore.get_iter(path)
00309             path = model.get_path(iter)[0]
00310             user_id        = model.get_value(iter, COLUMN_USERID)
00311             user_firstname = model.get_value(iter, COLUMN_FIRSTNAME)
00312             user_lastname  = model.get_value(iter, COLUMN_LASTNAME)
00313             model.remove(iter)
00314 
00315             # Add in the the left view
00316             self.add_user_in_model(self.model_left, (user_id, user_firstname, user_lastname))
00317             
00318             # Save the change in the base (1 Is the 'Unselected user' class)
00319             self.cur.execute('UPDATE users SET class_id=? where user_id=?', (1, user_id))
00320             self.con.commit()
00321             print "UPDATE users SET class_id=1"
00322 
00323     # Done, can quit this dialog (without saving)
00324     #
00325     def close(self, button):
00326 
00327         self.list_class.reload(self.class_id,
00328                                self.class_name,
00329                                self.teacher_name)
00330         self.destroy()
00331         
00332     # Done, can quit this dialog with saving
00333     #
00334     def ok(self, button):
00335 
00336         # Tell the user he must provide enough information
00337         if(self.entry_class.get_text() == ""):
00338             dialog = gtk.MessageDialog(None,
00339                                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
00340                                        gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
00341                                        _("You need to provide at least a name for your class"))
00342             dialog.run()
00343             dialog.destroy()
00344             return
00345 
00346         #
00347         # Now everything is correct, create the class
00348         #
00349 
00350         class_data = (self.class_id,
00351                       self.entry_class.get_text(),
00352                       self.entry_teacher.get_text()
00353                       )
00354 
00355         if(self.new_class):
00356             self.create_class()
00357 
00358         # Save the changes in the base
00359         self.cur.execute('UPDATE class set name=?,teacher=? where class_id=?',
00360                          (self.entry_class.get_text(),
00361                           self.entry_teacher.get_text(),
00362                           self.class_id));
00363         self.con.commit()
00364 
00365         # Close the dialog window now
00366         # (The close code will refresh the class_list)
00367         self.class_name   = self.entry_class.get_text()
00368         self.teacher_name = self.entry_teacher.get_text()
00369 
00370         print "class_edit done"
00371         self.destroy()
00372 
00373 
00374     #
00375     # Create a class
00376     # Make the necessary checks and create the class in the base
00377     #
00378     def create_class(self):
00379                 
00380         # Check the login do not exist already
00381         self.cur.execute('SELECT name FROM class WHERE name=?',
00382                          (self.entry_class.get_text(),))
00383         if(self.cur.fetchone()):
00384             dialog = gtk.MessageDialog(None,
00385                                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
00386                                        gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
00387                                        _("There is already a class with this name"))
00388             dialog.run()
00389             dialog.destroy()
00390             return
00391 
00392         # Create its Whole group
00393         group_id = constants.get_next_group_id(self.con, self.cur)
00394         self.cur.execute('INSERT INTO groups (group_id, name, class_id, description) ' +
00395                          'VALUES ( ?, "All", ?, "All users")',
00396                          (group_id, self.class_id));
00397 
00398         class_data = (self.class_id,
00399                       self.entry_class.get_text(),
00400                       self.entry_teacher.get_text(),
00401                       group_id
00402                       )
00403 
00404         self.cur.execute('INSERT OR REPLACE INTO class (class_id, name, teacher, wholegroup_id) ' +
00405                          'values (?, ?, ?, ?)', class_data)
00406 
00407         # No more need to create this class, it's done
00408         self.new_class = False