Commit 6123ac46 authored by Guillaume Sabbagh's avatar Guillaume Sabbagh
Browse files
parents 529db12a 7323a04a
import demjson import demjson
import pickle
from Model import Model from Model import Model
from tk.MainWindow import MainWindow from tk.MainWindow import MainWindow
...@@ -19,7 +20,9 @@ class Controller: ...@@ -19,7 +20,9 @@ class Controller:
self._view=MainWindow(self) self._view=MainWindow(self)
""" """
IMPORT/EXPORT (JSON) IMPORT/EXPORT (JSON/BYTES)
- use JSON only for basic types (most complex must be iterable)
- use bytes for all others class (not secured)
""" """
def exportJSON(self, file:str, obj:object): def exportJSON(self, file:str, obj:object):
assert len(file)>5 and file[-4:]=="json" assert len(file)>5 and file[-4:]=="json"
...@@ -30,4 +33,14 @@ class Controller: ...@@ -30,4 +33,14 @@ class Controller:
assert len(file)>5 and file[-4:]=="json" assert len(file)>5 and file[-4:]=="json"
with open(file, "r") as jsonFile: with open(file, "r") as jsonFile:
return demjson.decode(jsonFile.read()) return demjson.decode(jsonFile.read())
\ No newline at end of file
def exportBYTES(self, file:str, obj:object):
assert len(file)>4 and file[-3:]=="obj"
with open(file, "wb") as bytesFile:
pickle.dump(obj,bytesFile)
def importBYTES(self, file:str):
assert len(file)>4 and file[-3:]=="obj"
with open(file, "rb") as bytesFile:
return pickle.load(bytesFile)
\ No newline at end of file
import pandas as pd import pandas as pd
from enum import Enum, unique
from ModelCallable import ModelCallable from ModelCallable import ModelCallable
from GrapheDeComposition import GrapheDeComposition, GC from GrapheDeComposition import GrapheDeComposition, GC, \
MorphismeGrapheDeComposition, MGC
from Categorie import Categorie
from Interaction import Interaction
from ChampPerceptif import ChampPerceptif
@unique
class ModelObjects(Enum):
GC="Graphe de Composition"
CI="Catégorie Indéxante"
It="Intéraction"
CP="Champ Perceptif"
class Model: class Model:
""" """
Contient tous les objets construits. Contient tous les objets construits.
""" """
_data=None _data=None
def __init__(self): def __init__(self):
self._data=pd.DataFrame(columns=["class","object"]) self._data=pd.DataFrame(columns=["class","object"])
self._data["class"]=self._data["class"].astype("string") self._data["class"]=self._data["class"].astype("string")
""" """
CREATION D'OBJETS CREATION D'OBJETS
""" """
...@@ -34,9 +45,11 @@ class Model: ...@@ -34,9 +45,11 @@ class Model:
self._data=self._data.append(newData, ignore_index=True) self._data=self._data.append(newData, ignore_index=True)
self.informObjectsAdded(list(range(i, self._data.index[-1]+1))) self.informObjectsAdded(list(range(i, self._data.index[-1]+1)))
def createGrapheDeComposition(self, objets:set = set(), nom:str = None): def createGrapheDeComposition(self, objets:set = set(), morphismes:set=set(), nom:str = None):
gc=GC(objets=objets, nom=nom) gc=GC(objets=objets, nom=nom)
self.addObject([gc]) self.addObject(gc)
gc|= objets
gc|= morphismes
""" """
GETTERS GETTERS
......
import threading
from typing import Callable
class OpThread(threading.Thread):
"""
Virtual class
Dispatch event went thread finished
"""
_operation=None
def __init__(self, operation:Callable) :
threading.Thread.__init__ (self)
self._operation=operation
def run(self):
self._operation()
class OpThreadWithEndEvent(OpThread):
"""
Virtual class
Dispatch event went thread finished
"""
_counter=0
_id=None
_root=None
_endEventName=None
def __init__(self, root, operation:Callable, receptEvent:Callable) :
OpThread.__init__ (self, operation)
self._root = root
self._id=OpThreadWithEndEvent._counter
OpThreadWithEndEvent._counter+=1
self._receptEvent=receptEvent
self._endEventName=f"<<op_thread_{self._id}_fini>>"
self._root.bind (self._endEventName, self._receptEvent)
def run(self):
"""
Overwrite
"""
self._root.event_generate(self._endEventName, x = self._operation())
from Controller import Controller from Controller import Controller
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -13,6 +13,7 @@ class MainWindow: ...@@ -13,6 +13,7 @@ class MainWindow:
_controller:None _controller:None
_root=None _root=None
def getRoot(self): return self._root
_frame=None _frame=None
_glFrame=None _glFrame=None
...@@ -46,11 +47,16 @@ class MainWindow: ...@@ -46,11 +47,16 @@ class MainWindow:
def _initFrames(self): def _initFrames(self):
# main frame # main frame
#test
#b=Button(self._root, text="test", command=lambda:self._controller.test(self._root))
#b.pack(fill=X)
# Frame
self._frame = Frame(self._root) self._frame = Frame(self._root)
self._frame.pack(expand=YES, fill=BOTH) self._frame.pack(expand=YES, fill=BOTH)
self._frame.columnconfigure(0, weight=1, minsize=500) self._frame.columnconfigure(0, weight=3, minsize=500)
self._frame.columnconfigure(1, weight=1, minsize=200) self._frame.columnconfigure(1, weight=1, minsize=200)
self._frame.columnconfigure(2, weight=1, minsize=200) self._frame.columnconfigure(2, weight=2, minsize=200)
self._frame.rowconfigure(0, weight=1, minsize=300) self._frame.rowconfigure(0, weight=1, minsize=300)
# OGL frame # OGL frame
...@@ -59,7 +65,7 @@ class MainWindow: ...@@ -59,7 +65,7 @@ class MainWindow:
self.initGLApp() self.initGLApp()
# Outils frame # Outils frame
self._outFrame = OutilsFrame(self._frame) self._outFrame = OutilsFrame(self._frame, self._controller)
self._outFrame.grid(row=0, column=1, sticky="nesw") self._outFrame.grid(row=0, column=1, sticky="nesw")
# Objets frame # Objets frame
...@@ -78,11 +84,11 @@ class MainWindow: ...@@ -78,11 +84,11 @@ class MainWindow:
fichierMenu=Menu(self._menu, tearoff=0) fichierMenu=Menu(self._menu, tearoff=0)
# >> Importer # >> Importer
importerMenu=Menu(fichierMenu, tearoff=0) importerMenu=Menu(fichierMenu, tearoff=0)
importerMenu.add_cascade(label="JSON", command=self.importerJSON) importerMenu.add_cascade(label="BYTES", command=self.importBYTES)
fichierMenu.add_cascade(label="Importer", menu=importerMenu) fichierMenu.add_cascade(label="Importer", menu=importerMenu)
# >> Exporter # >> Exporter
exporterMenu=Menu(fichierMenu, tearoff=0) exporterMenu=Menu(fichierMenu, tearoff=0)
exporterMenu.add_cascade(label="JSON", command=self.exporterJSON) exporterMenu.add_cascade(label="BYTES", command=self.exportBYTES)
exporterMenu.add_cascade(label="Graphviz", command=self.exporterGraphviz) exporterMenu.add_cascade(label="Graphviz", command=self.exporterGraphviz)
fichierMenu.add_cascade(label="Exporter", menu=exporterMenu) fichierMenu.add_cascade(label="Exporter", menu=exporterMenu)
# --------- # ---------
...@@ -96,34 +102,35 @@ class MainWindow: ...@@ -96,34 +102,35 @@ class MainWindow:
""" """
IMPORTS/EXPORTS IMPORTS/EXPORTS
""" """
def importerJSON(self): def importBYTES(self):
filepaths = filedialog.askopenfilenames(title="Importer un objet", filepaths = filedialog.askopenfilenames(title="Importer un objet",
filetypes=[('JSON file','.json')], filetypes=[('BYTES file','.obj')],
initialdir=getcwd()+"/JSON") initialdir=getcwd()+"/BYTES")
for filepath in filepaths: for filepath in filepaths:
self._controller.getModel().addObject(self._controller.importJSON(filepath)) self._controller.getModel().addObject(self._controller.importBYTES(filepath))
def exporterJSON(self): def exportBYTES(self):
uids=self._objFrame.getSelectedObjects() uids=self._objFrame.getSelectedObjects()
data=self._controller.getModel().getObject(uids) data=self._controller.getModel().getObject(uids)
if data.shape[0]==0: if data.shape[0]==0:
messagebox.showinfo(title="JSON Export", message="Aucun objet séléctionné.") messagebox.showinfo(title="BYTES Export", message="Aucun objet séléctionné.")
return return
elif data.shape[0]==1: elif data.shape[0]==1:
row=data.loc[0] row=data.loc[int(uids[0])]
filepath = filedialog.asksaveasfilename(title="Exporter un objet", filepath = filedialog.asksaveasfilename(title="Exporter un objet",
initialfile=str(row["class"])+str(data.index[0]), initialfile=str(row["class"])+str(data.index[0]),
filetypes=[('JSON file','.json')], filetypes=[('BYTES file','.obj')],
initialdir=getcwd()+"/JSON")+".json" initialdir=getcwd()+"/BYTES")+".obj"
self._controller.exportJSON(filepath, row["object"]) if filepath:
self._controller.exportBYTES(filepath, row["object"])
else: else:
ExportAsDialog(self, data=data) ExportAsDialog(self, data=data)
def multipleExportJSON(self, filepaths:list, data): def multipleExportJSON(self, filepaths:list, data):
i=0 i=0
for index, row in data.iterrows(): for index, row in data.iterrows():
self._controller.exportJSON(filepaths[i], row["object"]) self._controller.exportBYTES(filepaths[i], row["object"])
i+=1 i+=1
def exporterGraphviz(self): def exporterGraphviz(self):
......
from Parameters import parameters
from Model import ModelObjects
from tkinter import TOP, BOTTOM, LEFT, RIGHT, X, \ from GrapheDeComposition import MGC
LabelFrame, Frame, Label, Text
from tkinter.ttk import Combobox
NEW_OBJECTS_LIST=["GC - Garphe de composition",
"CI - Catégorie indexante",
"It - Interraction",
"CP - Champ perceptif"]
from re import split, findall
from tkinter import TOP, BOTTOM, LEFT, RIGHT, X, VERTICAL, \
LabelFrame, Frame, Label, Text, Scrollbar, Button
from tkinter.ttk import Combobox
class NewObjectFrame(LabelFrame): class NewObjectFrame(LabelFrame):
""" """
Frame objects Frame objects
""" """
_model=None
_NOList=None _NOList=None
_NOFrames=None _NOFrames={}
_frame=None _frame=None
def __init__(self, parent, *args, **kwargs): def __init__(self, parent, model, *args, **kwargs):
assert model and parent
LabelFrame .__init__(self, parent, LabelFrame .__init__(self, parent,
bd=2, text="Nouvel Objet", bd=parameters.FRAME_BD,
text="Nouvel Objet",
*args, **kwargs) *args, **kwargs)
self._model=model
self._initFrame() self._initFrame()
def _initFrame(self): def _initFrame(self):
values=[""]
for obj in ModelObjects:
values.append(obj.value)
self._NOList=Combobox(self, self._NOList=Combobox(self,
values=NEW_OBJECTS_LIST, values=values,
state='readonly') state='readonly')
self._NOList.pack(side = TOP, fill=X) self._NOList.pack(side = TOP, fill=X)
self._NOList.bind("<<ComboboxSelected>>", self.selectNOType) self._NOList.bind("<<ComboboxSelected>>", self.selectNOType)
...@@ -41,58 +46,115 @@ class NewObjectFrame(LabelFrame): ...@@ -41,58 +46,115 @@ class NewObjectFrame(LabelFrame):
def _initNOFrames(self): def _initNOFrames(self):
self._NOFrames=[Frame(self)] self._NOFrames=[Frame(self)]
for obj in ModelObjects:
self._NOFrames.append(NewGCFrame(self)) self._NOFrames.append(BuildObjectFrame(self, self._model, obj))
def selectNOType(self, event): def selectNOType(self, event):
self._frame=self._NOFrames[self._NOList.current()+1] self._frame.forget()
self._frame=self._NOFrames[self._NOList.current()]
self._frame.pack(side = TOP, fill=X) self._frame.pack(side = TOP, fill=X)
class BuildObjectFrame(Frame):
class NewGCFrame(Frame):
""" """
Frame New "GC - Graphe de composition" Frame New "GC - Graphe de composition"
""" """
_model=None
_obj=None
_validateButton=None
_textObjects=None
_textMorphismes=None _textMorphismes=None
def __init__(self, parent, *args, **kwargs): def __init__(self, parent, model, obj:ModelObjects, *args, **kwargs):
assert model and parent
Frame .__init__(self, parent, *args, **kwargs) Frame .__init__(self, parent, *args, **kwargs)
#self.configure(width=200, height=100) self._model=model
# self.columnconfigure(0, minsize =30) self._obj=obj
# self.columnconfigure(1, minsize =20)
#self.grid_propagate(False)
self._initFrame() self._initFrame()
def _initFrame(self): def _initFrame(self):
if self._obj==ModelObjects.GC:
self._initGrapheCompositionFrame()
#elif self._obj==ModelObjects.CI:
def _initGrapheCompositionFrame(self):
self.columnconfigure(0, weight=1, minsize =30)
self.rowconfigure(0, weight=1, minsize=20)
self.rowconfigure(1, weight=1, minsize=20)
self.rowconfigure(2, weight=1, minsize=20)
# Objects
self._textObjects=ObjectLabelText(self)
self._textObjects.grid(row=1, column=0)
# Morphismes
self._textMorphismes=MorphismeLabelText(self)
self._textMorphismes.grid(row=2, column=0)
# Button
def generate():
self._model.createGrapheDeComposition(objets=self._textObjects.getObjectsList(),
morphismes=self._textMorphismes.getMorphismesList(),
nom = None)
self._validateButton=Button(self, text="Générer", command=generate)
self._validateButton.grid(row=0, column=0, sticky="e")
labelObject=Label(self, text="Objets: ", class LabelText(LabelFrame):
height=1, width=20)
labelObject.grid(row=0, column=0)
self._textObjects=Text(self) _TEXT_MAX_SIZE=100
self._textObjects.grid(row=0, column=1) _text=None
_scrollbarY=None
labelMorphismes=Label(self, text="Morphismes: ", def __init__(self, parent, name:str, *args, **kwargs):
height=3, width=20) LabelFrame .__init__(self, parent,
labelMorphismes.grid(row=1, column=0) bd=parameters.FRAME_BD,
text=name,
*args, **kwargs)
self._initFrame()
self._textMorphismes=Text(self) def _initFrame(self):
self._textMorphismes.grid(row=1, column=1) self.columnconfigure(0, weight=1, minsize=20)
self.columnconfigure(1, minsize=16)
self.rowconfigure(0, weight=1, minsize=20)
self._text=Text(self)
self._text.grid(row=0, column=0, sticky="nw")
self._scrollbarY=Scrollbar(self, orient =VERTICAL)
self._scrollbarY.grid(row=0, column=1, sticky="nsw")
self._text.configure(yscrollcommand = self._scrollbarY.set)
self._scrollbarY.config(command=self._text.yview)
def getText(self):
return self._text.get("1.0",'end-1c')
class ObjectLabelText(LabelText):
def __init__(self, parent, *args, **kwargs):
LabelText .__init__(self, parent, name="Objets", *args, **kwargs)
def getObjectsList(self):
return [x for x in split('[,\n]', self.getText()) if x]
class MorphismeLabelText(LabelText):
def __init__(self, parent, *args, **kwargs):
LabelText .__init__(self, parent, name="Morphismes", *args, **kwargs)
def getMorphismesList(self):
# (...)
tuples=[x[1:-1] for x in findall("\([^\(\)]+\)", self.getText()) if x]
# ,\n
tuplesSplited=[[x for x in split('[,\n]', t) if x] for t in tuples]
# 3 chaînes
morphismesDescription=[x for x in tuplesSplited if len(x)==3]
# Création des morphismes
return [MGC(x[0],x[1],x[2]) for x in morphismesDescription]
......
...@@ -29,7 +29,7 @@ class ObjetsFrame(Frame, ModelCallable): ...@@ -29,7 +29,7 @@ class ObjetsFrame(Frame, ModelCallable):
self._controller.getModel().registerModelCallable(self) self._controller.getModel().registerModelCallable(self)
self.columnconfigure(0, weight=1, minsize=100) self.columnconfigure(0, weight=1, minsize=100)
self.columnconfigure(1, weight=1, minsize=16)#default value of scrollbar width self.columnconfigure(1, minsize=16)#default value of scrollbar width
self.rowconfigure(0, minsize=20) self.rowconfigure(0, minsize=20)
self.rowconfigure(1, weight=4, minsize=100) self.rowconfigure(1, weight=4, minsize=100)
......
...@@ -11,8 +11,12 @@ from tk.NewObjectFrame import NewObjectFrame ...@@ -11,8 +11,12 @@ from tk.NewObjectFrame import NewObjectFrame
class OutilsFrame(Frame): class OutilsFrame(Frame):
def __init__(self, parent, *args, **kwargs): _controller=None
def __init__(self, parent, controller, *args, **kwargs):
assert controller
Frame.__init__(self, parent, *args, **kwargs) Frame.__init__(self, parent, *args, **kwargs)
self._controller=controller
self.columnconfigure(0, weight=1, minsize=100) self.columnconfigure(0, weight=1, minsize=100)
self.rowconfigure(0, minsize=20) self.rowconfigure(0, minsize=20)
self.rowconfigure(1, weight=1, minsize=100) self.rowconfigure(1, weight=1, minsize=100)
...@@ -21,5 +25,5 @@ class OutilsFrame(Frame): ...@@ -21,5 +25,5 @@ class OutilsFrame(Frame):
def _initFrame(self): def _initFrame(self):
factory.buildSectionLabel(self,"Outils").grid(row=0, column=0, sticky="nwe") factory.buildSectionLabel(self,"Outils").grid(row=0, column=0, sticky="nwe")
NOFrame=NewObjectFrame(self) NOFrame=NewObjectFrame(self, self._controller.getModel())