Back to index

gcompris  8.2.2
profile_edit.py
Go to the documentation of this file.
00001 #  gcompris - profile_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 import profile_group_list
00026 
00027 import constants
00028 
00029 # Database
00030 from pysqlite2 import dbapi2 as sqlite
00031 
00032 # Group Management
00033 (
00034   COLUMN_GROUPID,
00035   COLUMN_CLASSNAME,
00036   COLUMN_GROUPNAME,
00037   COLUMN_DESCRIPTION,
00038 ) = range(4)
00039 
00040 
00041 class ProfileEdit(gtk.Window):
00042 
00043     def __init__(self, db_connect, db_cursor,
00044                  profile_id, profile_name, profile_description,
00045                  profile_list):
00046 
00047         # Create the toplevel window
00048         gtk.Window.__init__(self)
00049 
00050         self.cur = db_cursor
00051         self.con = db_connect
00052 
00053         self.profile_id = profile_id
00054 
00055         # A pointer to the profile_list_list class
00056         # Will be called to refresh the list when edit is done
00057         self.profile_list = profile_list
00058         
00059         self.set_title(_("Editing a Profile"))
00060         self.set_border_width(8)
00061         self.set_default_size(320, 350)
00062 
00063         if(profile_name):
00064             frame = gtk.Frame(_("Editing profile: ") + profile_name)
00065             self.new_profile = False
00066         else:
00067             frame = gtk.Frame(_("Editing a new profile"))
00068             self.new_profile = True
00069             profile_name =""
00070             profile_description = ""
00071 
00072 
00073         self.add(frame)
00074         
00075         vbox = gtk.VBox(False, 8)
00076         vbox.set_border_width(8)
00077         frame.add(vbox)
00078 
00079         # Label and Entry for the group and description
00080         table = gtk.Table(2, 2, homogeneous=False)
00081         table.set_border_width(0)
00082         table.set_row_spacings(0)
00083         table.set_col_spacings(20)
00084         vbox.pack_start(table, True, True, 0)
00085         
00086         label = gtk.Label(_('Profile:'))
00087         label.set_alignment(0, 0)
00088         table.attach(label, 0, 1, 0, 1, xoptions=gtk.SHRINK, yoptions=gtk.EXPAND)
00089         self.entry_profile = gtk.Entry()
00090         self.entry_profile.set_max_length(20)
00091         self.entry_profile.insert_text(profile_name, position=0)
00092         table.attach(self.entry_profile, 1, 2, 0, 1,
00093                      xoptions=gtk.SHRINK, yoptions=gtk.EXPAND)
00094 
00095         # FIXME: How to remove the selection
00096         
00097         # Label and Entry for the first name
00098         label = gtk.Label(_('Description:'))
00099         label.set_alignment(0, 0)
00100         table.attach(label, 0, 1, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.EXPAND)
00101         self.entry_description = gtk.Entry()
00102         self.entry_description.set_max_length(30)
00103         self.entry_description.insert_text(profile_description, position=0)
00104         table.attach(self.entry_description, 1, 2, 1, 2,
00105                      xoptions=gtk.SHRINK, yoptions=gtk.EXPAND)
00106 
00107 
00108         # Top message gives instructions
00109         label = gtk.Label(_('Assign all the groups belonging to this profile'))
00110         vbox.pack_start(label, False, False, 0)
00111         vbox.pack_start(gtk.HSeparator(), False, False, 0)
00112 
00113         # Lower area
00114         hbox = gtk.HBox(False, 8)
00115         vbox.pack_start(hbox, True, True, 0)
00116 
00117         # Left list
00118         # ---------
00119 
00120         # Create the table
00121         sw = gtk.ScrolledWindow()
00122         sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
00123         sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
00124 
00125         # create tree model
00126         self.model_left = self.__create_model(False, profile_id)
00127 
00128         # create tree view
00129         treeview = gtk.TreeView(self.model_left)
00130         treeview.set_rules_hint(True)
00131         treeview.set_search_column(COLUMN_GROUPNAME)
00132         treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
00133         
00134         sw.add(treeview)
00135         
00136         # add columns to the tree view
00137         self.__add_columns(treeview)
00138 
00139         hbox.pack_start(sw, True, True, 0)
00140 
00141 
00142         # Middle Button
00143         # -------------
00144         vbox2 = gtk.VBox(False, 8)
00145         vbox2.set_border_width(8)
00146         hbox.pack_start(vbox2, True, True, 0)
00147 
00148         button = gtk.Button(stock='gtk-add')
00149         button.connect("clicked", self.add_group, treeview)
00150         vbox2.pack_start(button, False, False, 0)
00151         button.show()
00152 
00153         button_delete = gtk.Button(stock='gtk-remove')
00154         vbox2.pack_start(button_delete, False, False, 0)
00155         button_delete.show()
00156 
00157 
00158         # Right List
00159         # ----------
00160 
00161         # Create the table
00162         sw2 = gtk.ScrolledWindow()
00163         sw2.set_shadow_type(gtk.SHADOW_ETCHED_IN)
00164         sw2.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
00165 
00166         # create tree model
00167         self.model_right = self.__create_model(True, profile_id)
00168 
00169         # create tree view
00170         treeview2 = gtk.TreeView(self.model_right)
00171         treeview2.set_rules_hint(True)
00172         treeview2.set_search_column(COLUMN_GROUPNAME)
00173         treeview2.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
00174 
00175         sw2.add(treeview2)
00176         
00177         # add columns to the tree view
00178         self.__add_columns(treeview2)
00179 
00180         hbox.pack_start(sw2, True, True, 0)
00181 
00182         # Confirmation Buttons
00183         # --------------------
00184         vbox.pack_start(gtk.HSeparator(), False, False, 0)
00185 
00186         bbox = gtk.HBox(homogeneous=False, spacing=8)
00187         
00188         button = gtk.Button(stock='gtk-help')
00189         bbox.pack_start(button, expand=False, fill=False, padding=0)
00190 
00191         button = gtk.Button(stock='gtk-ok')
00192         bbox.pack_end(button, expand=False, fill=False, padding=0)
00193         button.connect("clicked", self.ok)
00194 
00195         button = gtk.Button(stock='gtk-close')
00196         bbox.pack_end(button, expand=False, fill=False, padding=0)
00197         button.connect("clicked", self.close)
00198 
00199         vbox.pack_start(bbox, False, False, 0)
00200 
00201 
00202         # Missing callbacks
00203         button_delete.connect("clicked", self.remove_group, 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_group_in_model(self, model, group):
00215         iter = model.append()
00216         model.set (iter,
00217                    COLUMN_GROUPID,      group[COLUMN_GROUPID],
00218                    COLUMN_CLASSNAME,    group[COLUMN_CLASSNAME],
00219                    COLUMN_GROUPNAME,    group[COLUMN_GROUPNAME],
00220                    COLUMN_DESCRIPTION,  group[COLUMN_DESCRIPTION]
00221                    )
00222 
00223     # profile_id: only groups in this profile are inserted
00224     # If with = True,  create a list only with groups in the given profile_id
00225     #           False, create a list only with groups NOT this profile_id
00226     def __create_model(self, with, profile_id):
00227 
00228         model = gtk.ListStore(
00229             gobject.TYPE_INT,
00230             gobject.TYPE_STRING,
00231             gobject.TYPE_STRING,
00232             gobject.TYPE_STRING)
00233 
00234         # Grab the all the groups
00235         self.cur.execute('SELECT group_id,name,description FROM groups ORDER BY name')
00236         group_data = self.cur.fetchall()
00237 
00238         for group in group_data:
00239 
00240             group_id = group[0]
00241             # Check our group is already in the profile
00242             self.cur.execute('SELECT * FROM list_groups_in_profiles ' +
00243                              'WHERE profile_id=? AND group_id=?',
00244                              (profile_id, group_id))
00245             group_is_already = self.cur.fetchall()
00246 
00247             # Extract the class name of this group
00248             class_name = constants.get_class_name_for_group_id(self.con,
00249                                                                self.cur,
00250                                                                group_id)
00251 
00252             # Insert the class name in the group
00253             group = (group[0], class_name, group[1], group[2])
00254             
00255             if(with and group_is_already):
00256                 self.add_group_in_model(model, group)
00257             elif(not with and not group_is_already):
00258                 self.add_group_in_model(model, group)
00259 
00260         return model
00261 
00262     def __add_columns(self, treeview):
00263 
00264         model = treeview.get_model()
00265         
00266         # columns for class name
00267         renderer = gtk.CellRendererText()
00268         renderer.set_data("column", COLUMN_CLASSNAME)
00269         column = gtk.TreeViewColumn(_('Class'), renderer,
00270                                     text=COLUMN_CLASSNAME)
00271         column.set_sort_column_id(COLUMN_CLASSNAME)
00272         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00273         column.set_fixed_width(constants.COLUMN_WIDTH_CLASSNAME)
00274         treeview.append_column(column)
00275 
00276         # columns for group name
00277         renderer = gtk.CellRendererText()
00278         renderer.set_data("column", COLUMN_GROUPNAME)
00279         column = gtk.TreeViewColumn(_('Group'), renderer,
00280                                     text=COLUMN_GROUPNAME)
00281         column.set_sort_column_id(COLUMN_GROUPNAME)
00282         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00283         column.set_fixed_width(constants.COLUMN_WIDTH_GROUPNAME)
00284         treeview.append_column(column)
00285 
00286         # column for description
00287         renderer = gtk.CellRendererText()
00288         renderer.set_data("column", COLUMN_DESCRIPTION)
00289         column = gtk.TreeViewColumn(_('Description'), renderer,
00290                                     text=COLUMN_DESCRIPTION)
00291         column.set_sort_column_id(COLUMN_DESCRIPTION)
00292         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00293         column.set_fixed_width(constants.COLUMN_WIDTH_GROUPDESCRIPTION_EDIT)
00294         treeview.append_column(column)
00295 
00296 
00297     # Add a group from the left list to the right list
00298     #
00299     def add_group(self, button, treeview):
00300 
00301         model = treeview.get_model()
00302         
00303         treestore, paths = treeview.get_selection().get_selected_rows()
00304         
00305         paths.reverse()
00306         
00307         for path in paths:
00308             
00309             iter = treestore.get_iter(path)
00310             
00311             path = model.get_path(iter)[0]
00312             group_id           = model.get_value(iter, COLUMN_GROUPID)
00313             class_name         = model.get_value(iter, COLUMN_CLASSNAME)
00314             group_name         = model.get_value(iter, COLUMN_GROUPNAME)
00315             group_description  = model.get_value(iter, COLUMN_DESCRIPTION)
00316             model.remove(iter)
00317 
00318             # Add in the the right view
00319             self.add_group_in_model(self.model_right,
00320                                     (group_id, class_name, group_name, group_description))
00321             
00322             # Save the change in the base
00323             self.cur.execute('INSERT OR REPLACE INTO list_groups_in_profiles ' +
00324                              '(profile_id, group_id) VALUES (?, ?)',
00325                              (self.profile_id, group_id))
00326             self.con.commit()
00327 
00328 
00329     # Add a group from the left list to the right list
00330     #
00331     def remove_group(self, button, treeview):
00332 
00333         model = treeview.get_model()
00334         
00335         treestore, paths = treeview.get_selection().get_selected_rows()
00336         
00337         paths.reverse()
00338         
00339         for path in paths:
00340             
00341             iter = treestore.get_iter(path)
00342             
00343             path = model.get_path(iter)[0]
00344             group_id           = model.get_value(iter, COLUMN_GROUPID)
00345             class_name         = model.get_value(iter, COLUMN_CLASSNAME)
00346             group_name         = model.get_value(iter, COLUMN_GROUPNAME)
00347             group_description  = model.get_value(iter, COLUMN_DESCRIPTION)
00348             model.remove(iter)
00349 
00350             # Add in the the left view
00351             self.add_group_in_model(self.model_left,
00352                                     (group_id, class_name, group_name, group_description))
00353             
00354             # Save the change in the base
00355             self.cur.execute('DELETE FROM list_groups_in_profiles ' +
00356                              'WHERE profile_id=? AND group_id=?',
00357                              (self.profile_id, group_id))
00358             self.con.commit()
00359 
00360 
00361 
00362     # Done, can quit this dialog
00363     #
00364     def close(self, button):
00365         self.profile_list.reload_profile()
00366         self.destroy()
00367         
00368     # Done, can quit this dialog with saving
00369     #
00370     def ok(self, button):
00371 
00372         # Tell the user he must provide enough information
00373         if(self.entry_profile.get_text().strip() == ""):
00374             dialog = gtk.MessageDialog(None,
00375                                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
00376                                        gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
00377                                        _("You need to provide at least a name for your profile"))
00378             dialog.run()
00379             dialog.destroy()
00380             return
00381 
00382         #
00383         # Now everything is correct, create the profile
00384         #
00385 
00386         profile_data = (self.profile_id,
00387                         self.entry_profile.get_text().strip(),
00388                         self.entry_description.get_text()
00389                       )
00390 
00391         if(self.new_profile):
00392             # Check the login do not exist already
00393             self.cur.execute('SELECT name FROM profiles WHERE name=?',
00394                              (self.entry_profile.get_text(),))
00395             if(self.cur.fetchone()):
00396                 dialog = gtk.MessageDialog(None,
00397                                            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
00398                                            gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
00399                                            _("There is already a profile with this name"))
00400                 dialog.run()
00401                 dialog.destroy()
00402                 return
00403 
00404             # Create the new profile
00405             profile_id = constants.get_next_profile_id(self.con, self.cur)
00406             self.cur.execute('INSERT INTO profiles (profile_id, name, description) ' +
00407                              'VALUES ( ?, ?, ?)',
00408                              (profile_data));
00409         else:
00410             # Save the profile changes
00411             self.cur.execute('UPDATE profiles SET name=?, description=? where profile_id=?',
00412                              (self.entry_profile.get_text(),
00413                               self.entry_description.get_text(),
00414                               self.profile_id));
00415         self.con.commit()
00416 
00417         # Close the dialog window now
00418         self.profile_list.reload_profile()
00419 
00420         self.destroy()
00421