Tableau avec wxpython (wxgrid) - version 1.5

Description

Ce programme permet de créé un tableau comme sous Excel, d'insérer autant de colonne et de lignes qu'il veut, puis sauvegarder et restituer son document. Il a été conçu avec WxPython. Des améliorations on été apporté depuis la version 1.0 tel que la gestion des fichiers (explications dans l'aide du programme), et la modifications possibles des lignes et colonnes.

Source / Exemple :


# -*- coding: cp1252 -*-

### Importations ###

import wx
import  wx.grid as  gridlib
import sys
import os
import help_tableau

### Variables générales : Version du programme ###

Version_Programme = "1.5"
Version_Fichier = u"2.0"
Extensions_ouvrir = u"Fichier de sauvegarde Tableau (.savtx)|*.savtx|" + \
            "Fichier de sauvegarde Tableau (version 1) (.savt)|*.savt|Tout les fichiers|*.*"
Extensions_save = u"Fichier de sauvegarde Tableau (.savtx)|*.savtx|" + \
            "Tout les fichiers|*.*"

### Fonctions Prélimières : Création de listes automatiques ###

def titre_auto_col_lig(col,lig):
    liste_col = []
    liste_lig = []
    for i in range(col):
        liste_col.append(u"Colone " + str(i+1))
    for i in range(lig):
        liste_lig.append(u"Ligne " + str(i+1))
    return (liste_col,liste_lig)

### Classes Prélimières : Création d'une base de données ###

class Cellule_Donnees:
    def __init__(self,col,lig,contenu):
        self.col = col
        self.lig = lig
        self.contenu = contenu

    def sauvegarde(self):
        texte = u"Cellule\n"
        texte = texte + str(self.col) + u"\n"
        texte = texte + str(self.lig) + u"\n"
        texte = texte + self.contenu + u"\n"
        texte = texte + u"/Cellule\n"
        return texte

class Base_Donnees:
    def __init__(self,nb_lig,nb_col,nom_col,nom_lig):
        self.liste_cellules = []
        self.nb_lig = nb_lig
        self.nb_col = nb_col

        self.nom_col = nom_col
        self.nom_lig = nom_lig

    def ajouter_cellule(self,cellule):
        self.liste_cellules.append(cellule)

    def return_cellule(self,lig,col):
        for cellule in self.liste_cellules:
            if cellule.col == col and cellule.lig == lig:
                return cellule
        return 0

    def return_valeur(self,lig,col): # Inutile
        test = self.return_cellule(lig,col)
        if test != 0:
            return u''
        else:
            return test.contenu

    def supprimer_cellule(self,lig,col):
        test = self.return_cellule(lig,col)
        if test != 0:
            self.liste_cellules.remove(test)

    def change_contenu(self,lig,col,contenu):
        test = self.return_cellule(lig,col)
        if contenu == u"":
            self.supprimer_cellule(lig,col)
        elif test != 0:
            test.contenu = contenu
        else:
            cel = Cellule_Donnees(col,lig,contenu)
            self.ajouter_cellule(cel)

    def change_nom(self,num,col,nom):
        if col:
            self.nom_col.pop(num)
            self.nom_col.insert(num,nom)
        else:
            self.nom_lig.pop(num)
            self.nom_lig.insert(num,nom)

    def sauvegarder(self):
        texte = u"Tableau\n"
        texte = texte + str(Version_Fichier) + u"\n"
        texte = texte + str(self.nb_col) + u"\n"
        texte = texte + str(self.nb_lig) + u"\n"
        texte = texte + u"Nom_Lignes\n"
        for element in self.nom_lig:
            texte = texte + element + u"\n"
        texte = texte + u"/Nom_Lignes\nNom_Colones\n"
        for element in self.nom_col:
            texte = texte + element + u"\n"
        texte = texte + u"/Nom_Colones\n"
        for cellule in self.liste_cellules:
            texte = texte + cellule.sauvegarde()
        texte = texte + u"/Tableau\n"
        return texte

### Classes Graphique : Du pure wxPython ###

class Dialogue_Selecte(wx.Dialog):
    def __init__(self, parent, titre,lig,col):
        pre = wx.PreDialog()
        pre.Create(parent, -1, titre)

        self.parent=parent
        self.col = 1
            
        self.PostCreate(pre)

        sizer = wx.BoxSizer(wx.VERTICAL)
        
        box = wx.BoxSizer(wx.HORIZONTAL)
        radio1 = wx.RadioButton( self, -1, "Éditer la colone n°", style = wx.RB_GROUP )
        box.Add(radio1, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.nb_col_entree = wx.SpinCtrl(self, -1, "", size=(70,-1))
        self.nb_col_entree.SetRange(1,col)
        self.nb_col_entree.SetValue(1)
        box.Add(self.nb_col_entree, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        box2 = wx.BoxSizer(wx.HORIZONTAL)
        radio2 = wx.RadioButton( self, -1, "Éditer la ligne n°")
        box2.Add(radio2, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.nb_lig_entree = wx.SpinCtrl(self, -1, "", size=(70,-1))
        self.nb_lig_entree.SetRange(1,lig)
        self.nb_lig_entree.SetValue(1)
        box2.Add(self.nb_lig_entree, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        l = wx.StaticText(self, -1, u"Vous pouvez également modifier le nom en double cliquant sur la ligne ou la colone")
        l.SetFont(wx.Font(8, wx.SWISS, wx.ITALIC, wx.NORMAL))

        b = wx.Button(self, -1, u"Éditer la ligne ou la colone sélectionnée")
        b.SetDefault()

        sizer.Add(box, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        sizer.Add(box2, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        sizer.Add(l, 0, wx.ALIGN_CENTER|wx.ALL, 5)
        sizer.Add(b, 0, wx.CENTER|wx.ALL, 5)

        self.Bind(wx.EVT_RADIOBUTTON, self.select_lig, radio2)
        self.Bind(wx.EVT_RADIOBUTTON, self.select_col, radio1)
        self.Bind(wx.EVT_BUTTON, self.valide, b)

        btnsizer = wx.StdDialogButtonSizer()
            
        btn = wx.Button(self, wx.ID_CANCEL,u"Fermer cette fenêtre")

        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)

        sizer.Add(btnsizer, 0, wx.ALL|wx.CENTER, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)
        self.nb_lig_entree.Enable(False)

    def select_lig(self,evt=None):
        self.col = 0
        self.nb_lig_entree.Enable(True)
        self.nb_col_entree.Enable(False)

    def select_col(self,evt=None):
        self.col = 1
        self.nb_lig_entree.Enable(False)
        self.nb_col_entree.Enable(True)

    def valide(self,evt=None):
        if self.col:
            nom =  u"Colone"
            i = self.nb_col_entree.GetValue() - 1
            ancien = self.parent.base_de_donnees.nom_col[i]
        else:
            nom =  u"Ligne"
            i = self.nb_lig_entree.GetValue() - 1
            ancien = self.parent.base_de_donnees.nom_lig[i]

        self.Destroy()
        dlg = Dialogue_Change_Nom(self.parent,u'Modifier le nom de la ' + nom + ' ' + str(i + 1), i, nom, ancien)
        dlg.CenterOnScreen()
        val = dlg.ShowModal()

class Dialogue_Change_Nombre(wx.Dialog):
    def __init__(self, parent, titre):
        pre = wx.PreDialog()
        pre.Create(parent, -1, titre)

        self.parent=parent
            
        self.PostCreate(pre)

        sizer = wx.BoxSizer(wx.VERTICAL)

        l = wx.StaticText(self, -1, u"Si vous supprimer des lignes ou des colones il se peut que vous détruisiez de manière définitive certaines données")
        l.SetFont(wx.Font(8, wx.SWISS, wx.ITALIC, wx.NORMAL))
        
        box = wx.BoxSizer(wx.HORIZONTAL)
        label = wx.StaticText(self, -1, u"Nombre Colones : ")
        box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.nb_col_entree = wx.SpinCtrl(self, -1, "", size=(70,-1))
        self.nb_col_entree.SetRange(1,9999)
        self.nb_col_entree.SetValue(self.parent.colones)
        box.Add(self.nb_col_entree, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        box2 = wx.BoxSizer(wx.HORIZONTAL)
        label = wx.StaticText(self, -1, u"Nombre Lignes : ")
        box2.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.nb_lig_entree = wx.SpinCtrl(self, -1, "", size=(70,-1))
        self.nb_lig_entree.SetRange(1,9999)
        self.nb_lig_entree.SetValue(self.parent.lignes)
        box2.Add(self.nb_lig_entree, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        self.statue = wx.StaticText(self, -1, u"Aucune modifications des données")
        self.statue.SetForegroundColour(wx.GREEN)

        b = wx.Button(self, -1, u"Modifier le nombre de lignes et de colones")
        b.SetDefault()

        sizer.Add(l, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        sizer.Add(box, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        sizer.Add(box2, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        sizer.Add(self.statue, 0, wx.ALIGN_CENTER|wx.ALL, 5)
        sizer.Add(b, 0, wx.CENTER|wx.ALL, 5)

        self.Bind(wx.EVT_SPINCTRL, self.changement, self.nb_col_entree)
        self.Bind(wx.EVT_SPINCTRL, self.changement, self.nb_lig_entree)
        self.Bind(wx.EVT_BUTTON, self.valide, b)

        btnsizer = wx.StdDialogButtonSizer()
            
        btn = wx.Button(self, wx.ID_CANCEL,u"Fermer cette fenêtre")

        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)

        sizer.Add(btnsizer, 0, wx.ALL|wx.CENTER, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)

    def changement(self,evt=None):
        nb_lig = self.nb_lig_entree.GetValue()
        nb_col = self.nb_col_entree.GetValue()

        data = self.parent.base_de_donnees
        nb = 0
        for element in data.liste_cellules:
            if element.col >= nb_col or element.lig >= nb_lig:
                nb = nb + 1

        if nb > 0:
            self.statue.SetLabel(u"Destruction de " + str(nb) + u" cellule(s) contenant des données")
            self.statue.SetForegroundColour(wx.RED)
        else:
            self.statue.SetLabel(u"Aucune modifications des données")
            self.statue.SetForegroundColour(wx.GREEN)

    def valide(self,evt=None):
        nb_lig = self.nb_lig_entree.GetValue()
        nb_col = self.nb_col_entree.GetValue()

        data = self.parent.base_de_donnees
        supp = []
        i = 0
        for element in data.liste_cellules:
            if element.col >= nb_col or element.lig >= nb_lig:
                i = i+ 1
                supp.append(element)

        for element in supp:
            data.liste_cellules.remove(element)
        print i
        
        nom_col = []
        nom_lig = []
        
        for i in range(nb_col):
            if i < len(data.nom_col):
                nom_col.append(data.nom_col[i])
            else:
                nom_col.append(u"Colone " + str(i+1))

        for i in range(nb_lig):
            if i < len(data.nom_lig):
                nom_lig.append(data.nom_lig[i])
            else:
                nom_lig.append(u"Ligne " + str(i+1))

        data.nb_lig = nb_lig
        data.nb_col = nb_col

        data.nom_col = nom_col
        data.nom_lig = nom_lig

        self.parent.ajuster_tableau(nb_lig,nb_col)
        for cellule in data.liste_cellules:
            self.parent.tableau.SetCellValue(cellule.lig,cellule.col,cellule.contenu)
        self.Destroy()
                

class Dialogue_Change_Nom(wx.Dialog):
    def __init__(self, parent, titre, num, nom, contenu):
        pre = wx.PreDialog()
        pre.Create(parent, -1, titre)

        self.parent=parent
        self.contenu = contenu
        self.numero = num
        self.nom = nom
            
        self.PostCreate(pre)

        sizer = wx.BoxSizer(wx.VERTICAL)        
        box = wx.BoxSizer(wx.HORIZONTAL)

        label = wx.StaticText(self, -1, u"Texte de la " + self.nom + u" " + str(self.numero + 1) + u' : ')
        box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.text = wx.TextCtrl(self, -1, self.contenu, size=(200,-1))
        box.Add(self.text, 1, wx.ALIGN_CENTRE|wx.ALL, 5)

        b = wx.Button(self, -1, u"Modifier le nom")
        b.SetDefault()

        sizer.Add(box, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        sizer.Add(b, 0, wx.CENTER|wx.ALL, 5)
        self.Bind(wx.EVT_BUTTON, self.valide, b)

        btnsizer = wx.StdDialogButtonSizer()
            
        btn = wx.Button(self, wx.ID_CANCEL,u"Fermer cette fenêtre")

        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)

        sizer.Add(btnsizer, 0, wx.ALL|wx.CENTER, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)

    def valide(self,evt):
        entree = self.text.GetValue().strip()
        if entree == u"":
            dal = wx.MessageDialog(self, u"Veuillez rentrer un nom à la " + self.nom,
                                   u'Erreur de saisie',wx.OK | wx.ICON_EXCLAMATION)
            dal.ShowModal()
            dal.Destroy()
        elif entree == u"/Nom_Colones" or entree == u"/Nom_Lignes":
            dal = wx.MessageDialog(self, u"Vous avez rentré un nom interdit.\n Il est interdit de rentrer '/Nom_Colones' ou '/Nom_Lignes'",
                                   u'Erreur de saisie',wx.OK | wx.ICON_EXCLAMATION)
            dal.ShowModal()
            dal.Destroy()
        else:
            if self.nom == "Colone":
                a = 1
            else:
                a = 0
            self.parent.base_de_donnees.change_nom(self.numero,a,entree)
            self.parent.titre_col_lig()
            self.parent.enr = 1
            self.parent.message_save()
            self.Destroy()

class Fenetre(wx.Frame):
    def __init__(self, parent, title,nb_lig=5,nb_col=5):
        wx.Frame.__init__(self, parent, -1, title, size=(800, 400))
        self.SetIcon(wx.Icon("Data\\icone_tableau.ico", wx.BITMAP_TYPE_ICO))
        self.Bind(wx.EVT_CLOSE, self.quitter)

        BarreMenu = wx.MenuBar()
        
        fichier = wx.Menu()
        fichier.Append(11, u"&Nouveau\tCtrl+N", u"Charger un document vierge")
        fichier.Append(12, u"Nouvelle &fenêtre", u"Créer une nouvelle fenêtre de tableau")
        fichier.AppendSeparator()
        fichier.Append(13, u"&Ouvrir\tCtrl+O", u"Ouvrir le tableau précédement sauvegardé")
        fichier.Append(14, u"&Enregistrer\tCtrl+S", u"Sauvegarder le tableau")
        fichier.Append(15, u"&Enregistrer sous ...\tCtrl+Shift+S", u"Sauvegarder le tableau dans un fichier particuier")
        fichier.AppendSeparator()
        fichier.Append(16, u"&Quitter\tAlt+F4", u"Quitter le programme d'exemple")
        BarreMenu.Append(fichier, u"&Fichier")

        option = wx.Menu()
        option.Append(21, u"Changer le &nom des lignes et colones", u"Permet de sélectionner la ligne ou la colone a renomer")
        option.Append(22, u"Configurer le nom&bre des lignes et colones", u"Permet de changer le nombre de lignes et/ou de colones")
        BarreMenu.Append(option, u"&Options")

        aide = wx.Menu()
        aide.Append(31, u"&Aide\tF1", u"Optenir de l'aide sur le programme")
        aide.Append(32, u"À &propos de ...\tF2", u"Informations divers sur le programme")
        BarreMenu.Append(aide, u"&Aide")

        self.Bind(wx.EVT_MENU, self.nouveau, id=11)
        self.Bind(wx.EVT_MENU, self.new_fenetre, id=12)
        self.Bind(wx.EVT_MENU, self.pre_ouvrir, id=13)
        self.Bind(wx.EVT_MENU, self.save, id=14)
        self.Bind(wx.EVT_MENU, self.pre_save, id=15)
        self.Bind(wx.EVT_MENU, self.quitter, id=16)

        self.Bind(wx.EVT_MENU, self.select_edit, id=21)
        self.Bind(wx.EVT_MENU, self.modif_nb, id=22)

        self.Bind(wx.EVT_MENU, self.aide, id=31)
        self.Bind(wx.EVT_MENU, self.about, id=32)
        
        self.SetMenuBar(BarreMenu)

        self.sb = wx.StatusBar(self)
        self.sb.SetFieldsCount(2)
        self.sb.SetStatusWidths([-1, -1])
        
        self.SetStatusBar(self.sb)

        self.lignes = nb_lig
        self.colones = nb_col
        self.enr = 0
        self.chemain_fichier = u"Pas encore enregistré"
        
        l_col,l_lig = titre_auto_col_lig(self.colones,self.lignes)        
        self.base_de_donnees = Base_Donnees(self.lignes,self.colones,l_col,l_lig)

        
        panel = wx.Panel(self)

        self.tableau = gridlib.Grid(panel,-1,size=(800,300))
        self.tableau.CreateGrid(self.lignes,self.colones)

        self.titre_col_lig()        
        self.tableau.Bind(gridlib.EVT_GRID_CELL_CHANGE, self.changement)
        self.tableau.Bind(gridlib.EVT_GRID_LABEL_LEFT_DCLICK, self.edite)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.tableau, 1, wx.ALL|wx.GROW, 10)
        panel.SetSizer(sizer)
        panel.Layout()
        self.Centre()

        self.message_save()

    def quitter(self,evt=None):
        if self.enr:
            dal = wx.MessageDialog(self, u"Vous n'avais pas sauvegarder les modifications de ce fichier.\nVoullez vous enregistrer avant de quitter ?",
                                       u"Confirmation de fermeture",wx.YES_NO|wx.CANCEL| wx.ICON_QUESTION)
            test = dal.ShowModal()
            dal.Destroy()
            if test == wx.ID_YES:
                test = self.save()
                if test:
                    self.Destroy()
            elif test == wx.ID_NO:
                self.Destroy()
        else:
            self.Destroy()

    def message_save(self,evt=None):
        if self.enr:
            texte = u"*" + self.chemain_fichier
        else:
            texte = self.chemain_fichier
        self.sb.SetStatusText(texte, 1)

    def nouveau(self,evt=None):
        ok = 0
        if self.enr:
            dal = wx.MessageDialog(self, u"Vous n'avais pas sauvegarder les modifications de ce fichier.\nVoullez vous enregistrer avant de réinitialiser ?",
                                       u"Confirmation de réinitialisation",wx.YES_NO|wx.CANCEL| wx.ICON_QUESTION)
            test = dal.ShowModal()
            dal.Destroy()
            if test == wx.ID_YES:
                test = self.save()
                if test:
                    ok = 1
            elif test == wx.ID_NO:
                ok = 1
        else:
            ok = 1

        if ok:
            self.ajuster_tableau(5,5)
            
            l_col,l_lig = titre_auto_col_lig(self.colones,self.lignes)        
            self.base_de_donnees = Base_Donnees(self.lignes,self.colones,l_col,l_lig)
            self.titre_col_lig()
            self.enr = 0
            self.chemain_fichier = u"Pas encore enregistré"
            self.message_save()

    def new_fenetre(self,evt=None):
        frame = Fenetre(None, u"Démonstration de sauvegarde & de wxGrid")
        frame.Show(True)

    def changement(self,evt):
        lig = evt.GetRow()
        col = evt.GetCol()
        valeur = self.tableau.GetCellValue(lig,col)
        self.base_de_donnees.change_contenu(lig,col,valeur)
        self.enr = 1
        self.message_save()

    def select_edit(self,evt=None):
        dlg = Dialogue_Selecte(self,u'Sélectionner la ligne ou la colone à modifier',self.lignes,self.colones)
        dlg.CenterOnScreen()
        val = dlg.ShowModal()

    def edite(self,evt):
        lig,col = evt.GetRow(), evt.GetCol()
        if lig == -1 and not (col == -1):
            nom =  u"Colone"
            i = col
            ancien = self.base_de_donnees.nom_col[i]
        elif col == -1 and not (lig == -1):
            nom =  u"Ligne"
            i = lig
            ancien = self.base_de_donnees.nom_lig[i]
        else:
            return

        dlg = Dialogue_Change_Nom(self,u'Modifier le nom de la ' + nom + ' ' + str(i + 1), i, nom, ancien)
        dlg.CenterOnScreen()
        val = dlg.ShowModal()

    def modif_nb(self,evt=None):
        dlg = Dialogue_Change_Nombre(self,u'Modifier le nombre de lignes et de colones')
        dlg.CenterOnScreen()
        val = dlg.ShowModal()

    def aide(self,evt=None):
        dlg = help_tableau.Aide(self)
        dlg.Show(True)
        dlg.CenterOnScreen() 
        
    def about(self,evt=None):
        dlg = help_tableau.About(self, -1, u"À propos de ...")
        dlg.CenterOnScreen()
        val = dlg.ShowModal() 
        
    def save(self,evt=None):
        if self.chemain_fichier == u"Pas encore enregistré" or not(self.chemain_fichier.split(u".")[-1] == u"savtx"):
            test = self.pre_save()
            return test
        else:
            self.sauvegarder(self.chemain_fichier)
            return 1

    def pre_save(self,evt=None):
        dlg = wx.FileDialog(self, message=u"Enregistrer le Tableau", defaultDir=os.getcwd(), 
            defaultFile="", wildcard=Extensions_save, style=wx.SAVE)
        
        if dlg.ShowModal() == wx.ID_OK:            
            fichier = dlg.GetPath()
            self.sauvegarder(fichier)
            return 1
        else:
            return 0

    def sauvegarder(self,chemain):
        donnees = self.base_de_donnees.sauvegarder()

        tete = u"""File Proction Data - Tableau
Exemple Aera Tableau
Version """ + Version_Programme

        ecrire = tete + u'\n' + donnees
        try:
            fichier = open(chemain,u"Uw") # Fonctionne jusqu'à Python 2.5 (?)
        except:
            try:
                fichier = open(chemain,u"w") # Fonctionne depuis Python 2.6 (?) (Choix automatique :p)
            except:
                dal = wx.MessageDialog(self, u"Impossible d'enregistrer le fichier. Erreur dans la création du fichier",
                                   u"Erreur grave",wx.OK | wx.ICON_ERROR)
                dal.ShowModal()
                dal.Destroy()
                return

        try:
            fichier.write(ecrire.encode(u"utf-8")) # Encodage pour les chaines de carractères Unicode
            fichier.close()
        except:
            dal = wx.MessageDialog(self, u"Impossible d'enregistrer le fichier. Erreur dans l'écriture",
                                   u"Erreur grave",wx.OK | wx.ICON_ERROR)
            dal.ShowModal()
            dal.Destroy()
        finally:
            fichier.close()
        self.enr = 0
        self.chemain_fichier = chemain
        self.message_save()

    def titre_col_lig(self):
        for i in range(len(self.base_de_donnees.nom_col)):
            self.tableau.SetColLabelValue(i,self.base_de_donnees.nom_col[i])
        for i in range(len(self.base_de_donnees.nom_lig)):
            self.tableau.SetRowLabelValue(i,self.base_de_donnees.nom_lig[i])
        self.tableau.SetColLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_BOTTOM)

    def ajuster_tableau(self,new_lig,new_col):
        self.tableau.ClearGrid()
        
        delta_lignes = self.lignes - new_lig
        delta_colones = self.colones - new_col

        if delta_lignes >0:
            for i in range(delta_lignes):
                self.tableau.DeleteRows()
        elif delta_lignes <0:
            for i in range(-delta_lignes):
                self.tableau.AppendRows()
        if delta_colones >0:
            for i in range(delta_colones):
                self.tableau.DeleteCols()
        elif delta_colones <0:
            for i in range(-delta_colones):
                self.tableau.AppendCols()

        self.lignes = new_lig
        self.colones = new_col
        
        self.titre_col_lig()

    def pre_ouvrir(self,evt=None):
        ok = 0
        if self.enr:
            dal = wx.MessageDialog(self, u"Vous n'avais pas sauvegarder les modifications de ce fichier.\nVoullez vous enregistrer avant d'ouvrir ?",
                                       u"Confirmation de réinitialisation",wx.YES_NO|wx.CANCEL| wx.ICON_QUESTION)
            test = dal.ShowModal()
            dal.Destroy()
            if test == wx.ID_YES:
                test = self.save()
                if test:
                    ok = 1
            elif test == wx.ID_NO:
                ok = 1
        else:
            ok = 1

        if ok:
            dlg = wx.FileDialog(
                self, message=u"Ouvrir un fichier Tableau", defaultDir=os.getcwd(), 
                defaultFile="", wildcard=Extensions_ouvrir, style=wx.OPEN)
            
            if dlg.ShowModal() == wx.ID_OK:
                fichier = dlg.GetPaths()[0]
                self.ouvrir(fichier)
        
        
    def ouvrir(self,chemain):
        err = 0
        if not(os.path.isfile(chemain)):
            dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir n'existe pas !",
                                   u"Erreur d'utilisation",wx.OK | wx.ICON_ERROR)
            dal.ShowModal()
            dal.Destroy()
            err = 1
        else:
            try:
                fichier = open(chemain,u"Ur") # Fonctionne jusqu'à Python 2.5 (?)
            except:
                try:
                    fichier = open(chemain,u"r") # Fonctionne depuis Python 2.6 (?) (Choix automatique :p)
                except:
                    dal = wx.MessageDialog(self, u"Problème lors de l'ouverture du fichier.\nImpossible d'ouvrir le fichier",
                                       u'Grave erreur',wx.OK | wx.ICON_ERROR)
                    dal.ShowModal()
                    dal.Destroy()
                    err = 1

        if not(err):
            try:
                l1 = fichier.readline().decode(u"utf-8")[:-1]
                if l1 == u"File Proction Data - Tableau":
                    l2 = fichier.readline().decode(u"utf-8")[:-1]
                    if l2 == u"Exemple Aera Tableau":
                        l3 = fichier.readline().decode(u"utf-8")[:-1]
                        if u"Version" in l3:
                            version = l3[8:]
                            l4 = fichier.readline().decode(u"utf-8")[:-1]
                            if l4 == u"Tableau":
                                version_file = fichier.readline().decode(u"utf-8")[:-1]
                                if version_file == u"2.0":
                                    test = self.ouvrir_version_2_0(fichier)
                                    if test:
                                        self.enr = 0
                                        self.chemain_fichier = chemain
                                        self.message_save()
                                else:
                                    dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir est bien un fichier Tableau mais " + \
                                                           u"à une version non prise en compte",u"Erreur à l'ouverture",wx.OK | wx.ICON_EXCLAMATION)
                                    dal.ShowModal()
                                    dal.Destroy()
                                    fichier.close()
                            else:
                                dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir est corrompu",
                                       u"Erreur à l'ouverture",wx.OK | wx.ICON_ERROR)
                                dal.ShowModal()
                                dal.Destroy()
                                fichier.close()
                        else:
                            dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir est corrompu",
                                       u"Erreur à l'ouverture",wx.OK | wx.ICON_ERROR)
                            dal.ShowModal()
                            dal.Destroy()
                            fichier.close()
                    else:
                        dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir ne correspond pas au programme",
                                       u"Erreur à l'ouverture",wx.OK | wx.ICON_ERROR)
                        dal.ShowModal()
                        dal.Destroy()
                        fichier.close()
        
                elif l1 == u"Tableau v1":
                    test = self.ouvrir_version_1(fichier)
                    if test:
                        self.enr = 0
                        self.chemain_fichier = chemain
                        self.message_save()
                else:
                    dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir ne correspond pas au programme",
                                       u"Erreur à l'ouverture",wx.OK | wx.ICON_ERROR)
                    dal.ShowModal()
                    dal.Destroy()
                    fichier.close()
                    
            except:
                dal = wx.MessageDialog(self, u"Impossible de lire les données dans le fichier",
                                       u"Erreur à l'ouverture",wx.OK | wx.ICON_ERROR)
                dal.ShowModal()
                dal.Destroy()
                fichier.close()

            

    def ouvrir_version_2_0(self,fichier):
        try :
            nb_col = fichier.readline().decode(u"utf-8")[:-1]
            nb_lig = fichier.readline().decode(u"utf-8")[:-1]

            nb_col, nb_lig = int(nb_col),int(nb_lig)

            l_lig = []
            l_col = []
                            
            fichier.readline().decode(u"utf-8")
            while 1:
                l = fichier.readline().decode(u"utf-8")
                if l == u"/Nom_Lignes\n":
                    break
                elif l == u"": # Au cas où on est au bout de programme pour évité la boucle infini
                    1/0  # On force le passage à l'exception (= Erreur)
                l_lig.append(l[:-1])
                                
            fichier.readline().decode(u"utf-8")
            while 1:
                l = fichier.readline().decode(u"utf-8")
                if l == u"/Nom_Colones\n":
                    break
                elif l == u"": # Au cas où on est au bout de programme pour évité la boucle infini
                    1/0  # On force le passage à l'exception (= Erreur)
                l_col.append(l[:-1])

            if not(nb_lig == len(l_lig) and nb_col == len(l_col)):
                1/0  # On force le passage à l'exception (= Erreur)
                            
            base_de_donnees_temp = Base_Donnees(nb_col, nb_lig,l_col,l_lig) # On crée une nouvelle base de données
        except:
            dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir est corrompu",
                                   u"Erreur à l'ouverture",wx.OK | wx.ICON_ERROR)
            dal.ShowModal()
            dal.Destroy()
            fichier.close()
            return 0 # Fin de la fonction :p
        
        
        while 1:
            ligne = fichier.readline().decode(u"utf-8")
            if ligne == u'':
                break
            elif ligne == u"Cellule\n":
                try:
                    col = fichier.readline().decode(u"utf-8")[:-1]
                    lig = fichier.readline().decode(u"utf-8")[:-1]
                    contenu = fichier.readline().decode(u"utf-8")[:-1]
                    lig , col = int(lig),int(col)
                    if 1<= lig+1 <= base_de_donnees_temp.nb_lig and 1<= col+1 <= base_de_donnees_temp.nb_col:
                        base_de_donnees_temp.change_contenu(lig,col,contenu)
                    else:
                        print "ok"
                        1/0 # On force le passage à l'exception (= Erreur)
                    if fichier.readline() != "/Cellule\n": # Vérification
                        1/0 # On force le passage à l'exception (= Erreur)
                except:
                    dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir est corrompu",
                                   u"Erreur à l'ouverture",wx.OK | wx.ICON_ERROR)
                    dal.ShowModal()
                    dal.Destroy()
                    fichier.close()
                    return 0 # Fin de la fonction :p

        fichier.close()

        self.base_de_donnees = base_de_donnees_temp
        self.ajuster_tableau(int(nb_lig),int(nb_col))
        for cellule in self.base_de_donnees.liste_cellules:
            self.tableau.SetCellValue(cellule.lig,cellule.col,cellule.contenu)
        return 1

    def ouvrir_version_1(self,fichier):
        try:
            l1 = fichier.readline()[:-1]
            l2 = fichier.readline()[:-1]
            l_col = eval(l1)
            l_lig = eval(l2)
            base_de_donnees_temp = Base_Donnees(len(l_col), len(l_lig),l_col,l_lig)
            while 1:
                ligne = fichier.readline().decode(u"utf-8")
                if ligne == u"":
                    break
                if ligne != u"\n":
                    ligne = ligne[17:]
                    a = eval(ligne)
                    lig = a[0]
                    col = a[1]
                    contenu = a[2]
                    
                    lig = int(lig)
                    col = int(col)
                    if 1<= lig+1 <= base_de_donnees_temp.nb_lig and 1<= col+1 <= base_de_donnees_temp.nb_col:
                        base_de_donnees_temp.change_contenu(lig,col,contenu)
                    else:
                        1/0 # On force le passage à l'exception (= Erreur)                
        except:
            dal = wx.MessageDialog(self, u"Le fichier que vous souhaitez ouvrir est corrompu",
                                   u"Erreur à l'ouverture",wx.OK | wx.ICON_ERROR)
            dal.ShowModal()
            dal.Destroy()
            fichier.close()
            return 0 # Fin de la fonction :p

        fichier.close()

        self.base_de_donnees = base_de_donnees_temp
        self.ajuster_tableau(len(l_lig),len(l_col))
        for cellule in self.base_de_donnees.liste_cellules:
            self.tableau.SetCellValue(cellule.lig,cellule.col,cellule.contenu)
        return 1
        

if 1: # Lancement de l'application
    app = wx.PySimpleApp(redirect=True)
    app.SetAppName(u"Tableau - Aéra")
    if len(sys.argv) >1:
        fichier = sys.argv[1] # Si il y a des argument supplémentaire on ne s'en occupe pas !
        frame = Fenetre(None, u"Démonstration de sauvegarde & de wxGrid")
        frame.ouvrir(fichier)
    else:
        frame = Fenetre(None, u"Démonstration de sauvegarde & de wxGrid")
    frame.Show(True)
    app.MainLoop()

Conclusion :


POUR CEUX QUI DÉSIR TÉLÉCHARGER WX.PYTHON :

Allez sur le site http://www.wxpython.org/download.php et sélectionner la version correspondant à votre version de Python et à votre système d'exploitation.

POUR FONCTIONNER LE PROGRAMME PRINCIPALE DOIT ÊTRE DANS LE MÊME DOSSIER QUE LE MODULE help_tableau.py ET QUE LE DOSSIER Data
CES DEUX DÉPENDANCES SONT DANS LE ZIP

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.