1 # -*- coding: utf-8 -*-
2 #Author: Pierre Ratinaud
3 #Copyright (c) 2022 Pierre Ratinaud
9 from wx.lib.splitter import MultiSplitterWindow
17 def __init__(self, pathout = None):
18 self.pathout = pathout
19 self.cate = self.readjson()
20 self.lenwords = len(self.cate['TOCATE']) + len([word for categorie in self.cate['CATE'] for word in self.cate['CATE'][categorie][1]])
23 if self.pathout is not None :
24 with open(self.pathout['cate.json'], 'r', encoding='utf8') as f :
27 cate = {'TOCATE' : {'word1': 3, 'word2' : 2, 'word3' : 5}, 'CATE': {'cat1' : [34,{'word6':30, 'word7':4}], 'cat2' : [20,{'word20':20}]}}
31 with open(self.pathout['cate.json'], 'w', encoding='utf8') as f :
32 f.write(json.dumps(self.cate, indent=4))
41 for val in self.cate['CATE'] :
42 cate.append([i, [val, self.cate['CATE'][val][0]]])
46 def getwordstocate(self) :
49 for val in self.cate['TOCATE'] :
50 words.append([i, [val, self.cate['TOCATE'][val]]])
54 def getcatewords(self, cat) :
57 if cat not in self.cate['CATE'] :
59 for val in self.cate['CATE'][cat][1] :
60 catewords.append([i, [val, self.cate['CATE'][cat][1][val]]])
62 return dict(catewords)
64 def getwordscate(self) :
66 for word in self.cate['TOCATE'] :
68 for categorie in self.cate['CATE'] :
69 for word in self.cate['CATE'][categorie][1] :
73 def addwordincate(self, categorie, word, eff) :
74 self.cate['CATE'][categorie][1][word] = eff
75 self.cate['CATE'][categorie][0] += eff
76 del(self.cate['TOCATE'][word])
78 def addwordinwords(self, categorie, word, eff) :
79 print(categorie, word, eff)
80 self.cate['TOCATE'][word] = eff
81 self.cate['CATE'][categorie][0] -= eff
82 del(self.cate['CATE'][categorie][1][word])
83 if self.cate['CATE'][categorie][0] == 0 :
84 del(self.cate['CATE'][categorie])
86 def findcatefromword(self, word) :
87 for categorie in self.cate['CATE'] :
88 if word in self.cate['CATE'][categorie][1] :
92 def changewordcate(self, newcate, word, eff) :
93 oldcat = self.findcatefromword(word)
94 del(self.cate['CATE'][oldcat][1][word])
95 self.cate['CATE'][oldcat][0] -= eff
96 self.cate['CATE'][newcate][1][word] = eff
97 self.cate['CATE'][newcate][0] += eff
98 if self.cate['CATE'][oldcat][0] == 0 :
99 del(self.cate['CATE'][oldcat])
101 def addcatefromwordtocate(self, word, eff) :
102 if word in self.cate['CATE'] :
105 self.cate['CATE'][word]=[eff,{word:eff}]
106 del(self.cate['TOCATE'][word])
109 def addcatefromscratch(self) :
111 while "NewCategory_%i" %i in self.cate['CATE'] :
113 newcate = "NewCategory_%i" %i
114 self.cate['CATE'][newcate] = [0, {}]
116 def addcatefromwordcate(self, word, eff) :
117 if word in self.cate['CATE'] :
120 oldcat = self.findcatefromword(word)
121 self.cate['CATE'][word]=[eff,{word:eff}]
122 del(self.cate['CATE'][oldcat][1][word])
123 self.cate['CATE'][oldcat][0] -= eff
124 if self.cate['CATE'][oldcat][0] == 0 :
125 del(self.cate['CATE'][oldcat])
128 def delcate(self, categorie) :
129 for word in self.cate['CATE'][categorie][1] :
130 self.cate['TOCATE'][word] = self.cate['CATE'][categorie][1][word]
131 del(self.cate['CATE'][categorie])
133 def loadcate(self, infile) :
134 if self.cate['CATE'] != {} :
135 print("Categories should be empty")
137 with open(infile, 'r', encoding='utf8') as f :
138 newcate = json.load(f)
139 for categorie in newcate['CATE'] :
140 self.cate['CATE'][categorie] = [0,{}]
141 for word in newcate['CATE'][categorie][1] :
142 if word in self.cate['TOCATE'] :
143 self.cate['CATE'][categorie][1][word] = self.cate['TOCATE'][word]
144 self.cate['CATE'][categorie][0] += self.cate['TOCATE'][word]
145 del(self.cate['TOCATE'][word])
148 totocat = sum([self.cate['TOCATE'][word] for word in self.cate['TOCATE']])
149 nbtocat = len(self.cate['TOCATE'])
150 nbcate = len(self.cate['CATE'])
151 totcate = sum([self.cate['CATE'][categorie][0] for categorie in self.cate['CATE']])
152 lenwordincate = len([word for categorie in self.cate['CATE'] for word in self.cate['CATE'][categorie][1]])
153 return nbtocat, totocat, nbcate, totcate, lenwordincate
159 #class ElCategorizator ( wx.Panel ):
161 # def __init__( self, parent, pathout, tableau, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.TAB_TRAVERSAL, name = wx.EmptyString ):
162 # wx.Panel.__init__ ( self, parent, id = id, pos = pos, size = size, style = style, name = name )
163 # self.pathout = pathout
164 # self.parent = parent
165 # self.tableau = tableau
167 # self.cate = CategoDict(self.pathout)
168 # gsizer = wx.BoxSizer( wx.VERTICAL )
170 # bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
172 # self.m_listToCate = ListForWords(self, dlist = self.cate, first = ['eff'])
173 # bSizer1.Add( self.m_listToCate, 2, wx.ALL|wx.EXPAND, 5 )
175 # self.m_listCate = ListForCate(self, dlist = self.cate, first = ['eff'])
176 # bSizer1.Add( self.m_listCate, 1, wx.ALL|wx.EXPAND, 5 )
178 # self.m_listCateWords = ListForCateWords(self, dlist = self.cate, first = ['eff'])
179 # bSizer1.Add( self.m_listCateWords, 1, wx.ALL|wx.EXPAND, 5 )
181 # bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
183 # self.butsave = wx.Button( self, wx.ID_SAVE, u"Save", wx.DefaultPosition, wx.DefaultSize, 0 )
184 # bSizer2.Add( self.butsave, 0, wx.ALL, 5 )
186 # self.butcsv = wx.Button( self, wx.ID_ANY, u"Export Columns", wx.DefaultPosition, wx.DefaultSize, 0 )
187 # bSizer2.Add( self.butcsv, 0, wx.ALL, 5 )
189 # self.butdict = wx.Button( self, wx.ID_ANY, u"Export dictonary", wx.DefaultPosition, wx.DefaultSize, 0 )
190 # bSizer2.Add( self.butdict, 0, wx.ALL, 5 )
192 # self.butload = wx.Button( self, wx.ID_ANY, u"Load a categorization", wx.DefaultPosition, wx.DefaultSize, 0 )
193 # bSizer2.Add( self.butload, 0, wx.ALL, 5 )
195 # self.butaddcate = wx.Button( self, wx.ID_ANY, u"Add a category", wx.DefaultPosition, wx.DefaultSize, 0 )
196 # bSizer2.Add( self.butaddcate, 0, wx.ALL, 5 )
199 # bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
201 # self.nbword = """Words : {:d} ({:d}) | """
203 # self.stat = """ Words to categorize : {:d} ({}%) - {:d} ({}%) -- Categories : {:d} - {:d} ({}%) - {:d} ({}%)"""
204 ## nbtocat, totocat, nbcate, totcate = self.cate.makestat()
205 ## lenwords = self.cate.lenwords
206 ## totwords = totocat + totcate
207 ## prtocat = repr(nbtocat/lenwords)
208 ## prtotocat = repr(totocat/totwords)
209 ## prcate = repr(totcate/totwords)
210 # self.wordtxt = wx.StaticText(self, -1, "")
211 # bSizer3.Add( self.wordtxt, 0, wx.ALL, 5 )
212 # self.stattxt = wx.StaticText(self, -1, "")
213 # bSizer3.Add( self.stattxt, 0, wx.ALL, 5 )
216 # gsizer.Add( bSizer2, 0, wx.EXPAND, 5 )
217 # gsizer.Add( bSizer1, 2, wx.EXPAND, 5 )
218 # gsizer.Add( bSizer3, 0, wx.EXPAND, 5 )
220 # self.butsave.Bind(wx.EVT_BUTTON, self.OnSave)
221 # self.butcsv.Bind(wx.EVT_BUTTON, self.OnCSV)
222 # self.butdict.Bind(wx.EVT_BUTTON, self.OnDict)
223 # self.butsave.SetBackgroundColour((14, 242, 14, 255))
224 # self.butload.Bind(wx.EVT_BUTTON, self.OnLoad)
225 # self.butaddcate.Bind(wx.EVT_BUTTON, self.OnAddCate)
227 # self.SetSizer( gsizer )
230 # def __del__( self ):
234 # def OnLoad(self, event) :
235 # if len(self.cate.cate['CATE']) != 0 :
236 # message = wx.MessageDialog(self, _("Categories must be empty to load a categorization."), _("Information"), wx.OK|wx.ICON_WARNING)
237 # message.ShowModal()
240 # wildcard = "json|*.json|" \
242 # dlg = wx.FileDialog(
243 # self, message="Choose a file",
244 # defaultDir=self.pathout.dirout,
248 # wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST |
252 # if dlg.ShowModal() == wx.ID_OK:
253 # paths = dlg.GetPaths()
255 # self.cate.loadcate(path)
256 # self.m_listCate.RefreshData(self.cate.getcate())
257 # self.m_listToCate.RefreshData(self.cate.getwordstocate())
260 # def OnSave(self, event) :
262 # self.butsave.SetBackgroundColour((14, 242, 14, 255))
264 # def OnCSV(self, event) :
265 # wordscate = self.cate.getwordscate()
266 # newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
267 # for line in self.tableau.select_col(self.tableau.selected_col):
270 # newline.append(wordscate.get(word,word))
271 # newtab.append(newline)
272 # with open(self.pathout['tableout.csv'], 'w', encoding='utf8') as f :
273 # f.write('\n'.join(['\t'.join(line) for line in newtab]))
274 # message = wx.MessageDialog(self, _("Export successful\n%s" % self.pathout['tableout.csv']), _("Information"), wx.OK|wx.ICON_INFORMATION)
275 # message.ShowModal()
278 # def OnDict(self, event):
279 # with open(self.pathout['dictionnary.txt'], 'w', encoding='utf8') as f :
280 # for categorie in self.cate.cate['CATE'] :
281 # f.write(categorie + ': \t' + repr(self.cate.cate['CATE'][categorie][0]) + '\n')
282 # for word in self.cate.cate['CATE'][categorie][1] :
283 # f.write('\t' + word + ': \t' + repr(self.cate.cate['CATE'][categorie][1][word]) + '\n')
284 # for word in self.cate.cate['TOCATE'] :
285 # f.write(word + ':\t' + repr(self.cate.cate['TOCATE'][word]) + '\n')
286 # message = wx.MessageDialog(self, _("Export successful\n%s" % self.pathout['dictionnary.txt']), _("Information"), wx.OK|wx.ICON_INFORMATION)
287 # message.ShowModal()
291 # nbtocat, totocat, nbcate, totcate, lenwordincate = self.cate.makestat()
292 # totwords = totocat + totcate
293 # prtocat = repr(round((nbtocat/self.cate.lenwords) * 100 ,2))
294 # prtotocat = repr(round((totocat/totwords) * 100, 2))
295 # prcate = repr(round((totcate/totwords)*100, 2))
296 # prwordincate = repr(round((lenwordincate/self.cate.lenwords)*100, 2))
297 # self.stattxt.SetLabel(self.stat.format(nbtocat, prtocat, totocat, prtotocat, nbcate, lenwordincate, prwordincate, totcate, prcate))
299 # def OnAddToTable(self) :
300 # wordscate = self.cate.getwordscate()
301 # newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
302 # for line in self.tableau.select_col(self.tableau.selected_col):
305 # newline.append(wordscate.get(word,word))
306 # newtab.append(newline)
308 # def OnAddCate(self, evt) :
309 # print('add a category')
310 # print(self.m_listCate.GetItemCount())
311 # self.cate.addcatefromscratch()
312 # self.m_listCate.dlist = self.cate.getcate()
313 # self.m_listCate.RefreshData(self.m_listCate.dlist)
314 # self.m_listCate.SetSelection(self.m_listCate.GetItemCount() - 1)
318 class ListPanel(wx.Panel) :
319 def __init__(self, parent, gparent, List):
320 wx.Panel.__init__(self, parent, style=wx.BORDER_SUNKEN)
322 self.gparent = gparent
323 self.cate = gparent.cate
324 gsizer = wx.BoxSizer( wx.HORIZONTAL )
325 self.list = List(self, dlist = gparent.cate, first = ['eff'])
326 gsizer.Add(self.list, 5, wx.EXPAND, 5 )
327 self.SetSizer( gsizer )
332 self.gparent.OnStat()
334 class ElCategorizator ( wx.Panel ):
336 def __init__( self, parent, pathout, tableau, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.TAB_TRAVERSAL, name = wx.EmptyString ):
337 wx.Panel.__init__ ( self, parent, id = id, pos = pos, size = size, style = style, name = name )
338 self.pathout = pathout
340 self.tableau = tableau
342 self.cate = CategoDict(self.pathout)
343 gsizer = wx.BoxSizer( wx.VERTICAL )
345 bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
346 splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
347 self.splitter = splitter
348 #sizer = wx.BoxSizer(wx.HORIZONTAL)
349 #sizer.Add(splitter, 1, wx.EXPAND)
350 #self.SetSizer(sizer)
351 W,H = wx.GetTopLevelParent(self).GetSize()
361 panelwords = ListPanel(splitter, self, ListForWords)
362 splitter.AppendWindow(panelwords, splitsize)
363 panelcate = ListPanel(splitter, self, ListForCate)
364 splitter.AppendWindow(panelcate, splitsize)
365 panelwordscate = ListPanel(splitter, self, ListForCateWords)
366 splitter.AppendWindow(panelwordscate, splitsize)
367 self.m_listToCate = panelwords.list
368 self.m_listCate = panelcate.list
369 self.m_listCateWords = panelwordscate.list
372 bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
374 self.butsave = wx.Button( self, wx.ID_SAVE, u"Save", wx.DefaultPosition, wx.DefaultSize, 0 )
375 bSizer2.Add( self.butsave, 0, wx.ALL, 5 )
377 self.butcsv = wx.Button( self, wx.ID_ANY, u"Export Columns", wx.DefaultPosition, wx.DefaultSize, 0 )
378 bSizer2.Add( self.butcsv, 0, wx.ALL, 5 )
380 self.butdict = wx.Button( self, wx.ID_ANY, u"Export dictonary", wx.DefaultPosition, wx.DefaultSize, 0 )
381 bSizer2.Add( self.butdict, 0, wx.ALL, 5 )
383 self.butload = wx.Button( self, wx.ID_ANY, u"Load a categorization", wx.DefaultPosition, wx.DefaultSize, 0 )
384 bSizer2.Add( self.butload, 0, wx.ALL, 5 )
386 self.butaddcate = wx.Button( self, wx.ID_ANY, u"Add a category", wx.DefaultPosition, wx.DefaultSize, 0 )
387 bSizer2.Add( self.butaddcate, 0, wx.ALL, 5 )
390 bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
392 self.nbword = """Words : {:d} ({:d}) | """
394 self.stat = """ Words to categorize : {:d} ({}%) - {:d} ({}%) -- Categories : {:d} - {:d} ({}%) - {:d} ({}%)"""
395 for panel in [panelwords, panelcate, panelwordscate] :
396 panel.m_listToCate = self.m_listToCate
397 panel.m_listCate = self.m_listCate
398 panel.m_listCateWords = self.m_listCateWords
399 panel.butsave = self.butsave
401 # nbtocat, totocat, nbcate, totcate = self.cate.makestat()
402 # lenwords = self.cate.lenwords
403 # totwords = totocat + totcate
404 # prtocat = repr(nbtocat/lenwords)
405 # prtotocat = repr(totocat/totwords)
406 # prcate = repr(totcate/totwords)
407 self.wordtxt = wx.StaticText(self, -1, "")
408 bSizer3.Add( self.wordtxt, 0, wx.ALL, 5 )
409 self.stattxt = wx.StaticText(self, -1, "")
410 bSizer3.Add( self.stattxt, 0, wx.ALL, 5 )
413 gsizer.Add( bSizer2, 0, wx.EXPAND, 5 )
414 gsizer.Add( splitter, 2, wx.EXPAND, 5 )
415 gsizer.Add( bSizer3, 0, wx.EXPAND, 5 )
417 self.butsave.Bind(wx.EVT_BUTTON, self.OnSave)
418 self.butcsv.Bind(wx.EVT_BUTTON, self.OnCSV)
419 self.butdict.Bind(wx.EVT_BUTTON, self.OnDict)
420 self.butsave.SetBackgroundColour((14, 242, 14, 255))
421 self.butload.Bind(wx.EVT_BUTTON, self.OnLoad)
422 self.butaddcate.Bind(wx.EVT_BUTTON, self.OnAddCate)
424 self.SetSizer( gsizer )
432 def OnLoad(self, event) :
433 if len(self.cate.cate['CATE']) != 0 :
434 message = wx.MessageDialog(self, _("Categories must be empty to load a categorization."), _("Information"), wx.OK|wx.ICON_WARNING)
438 wildcard = "json|*.json|" \
441 self, message="Choose a file",
442 defaultDir=self.pathout.dirout,
446 wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST |
450 if dlg.ShowModal() == wx.ID_OK:
451 paths = dlg.GetPaths()
453 self.cate.loadcate(path)
454 self.m_listCate.RefreshData(self.cate.getcate())
455 self.m_listToCate.RefreshData(self.cate.getwordstocate())
458 def OnSave(self, event) :
460 self.butsave.SetBackgroundColour((14, 242, 14, 255))
462 def OnCSV(self, event) :
463 wordscate = self.cate.getwordscate()
464 newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
465 for line in self.tableau.select_col(self.tableau.selected_col):
468 newline.append(wordscate.get(word,word))
469 newtab.append(newline)
470 with open(self.pathout['tableout.csv'], 'w', encoding='utf8') as f :
471 f.write('\n'.join(['\t'.join(line) for line in newtab]))
472 message = wx.MessageDialog(self, _("Export successful\n%s" % self.pathout['tableout.csv']), _("Information"), wx.OK|wx.ICON_INFORMATION)
476 def OnDict(self, event):
477 with open(self.pathout['dictionnary.txt'], 'w', encoding='utf8') as f :
478 for categorie in self.cate.cate['CATE'] :
479 f.write(categorie + ': \t' + repr(self.cate.cate['CATE'][categorie][0]) + '\n')
480 for word in self.cate.cate['CATE'][categorie][1] :
481 f.write('\t' + word + ': \t' + repr(self.cate.cate['CATE'][categorie][1][word]) + '\n')
482 for word in self.cate.cate['TOCATE'] :
483 f.write(word + ':\t' + repr(self.cate.cate['TOCATE'][word]) + '\n')
484 message = wx.MessageDialog(self, _("Export successful\n%s" % self.pathout['dictionnary.txt']), _("Information"), wx.OK|wx.ICON_INFORMATION)
489 nbtocat, totocat, nbcate, totcate, lenwordincate = self.cate.makestat()
490 totwords = totocat + totcate
491 prtocat = repr(round((nbtocat/self.cate.lenwords) * 100 ,2))
492 prtotocat = repr(round((totocat/totwords) * 100, 2))
493 prcate = repr(round((totcate/totwords)*100, 2))
494 prwordincate = repr(round((lenwordincate/self.cate.lenwords)*100, 2))
495 self.stattxt.SetLabel(self.stat.format(nbtocat, prtocat, totocat, prtotocat, nbcate, lenwordincate, prwordincate, totcate, prcate))
498 def OnAddToTable(self) :
499 wordscate = self.cate.getwordscate()
500 newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
501 for line in self.tableau.select_col(self.tableau.selected_col):
504 newline.append(wordscate.get(word,word))
505 newtab.append(newline)
507 def OnAddCate(self, evt) :
508 print('add a category')
509 print(self.m_listCate.GetItemCount())
510 self.cate.addcatefromscratch()
511 self.m_listCate.dlist = self.cate.getcate()
512 self.m_listCate.RefreshData(self.m_listCate.dlist)
513 self.m_listCate.SetSelection(self.m_listCate.GetItemCount() - 1)
516 class ListForCate(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
518 def __init__(self, parent, dlist = {}, first = [], usefirst = False, menu = True):
519 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES|wx.LC_EDIT_LABELS|wx.LC_SINGLE_SEL)
521 self.cate = self.parent.cate
522 self.dlist= self.cate.getcate()
524 self.il = wx.ImageList(20, 20)
525 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION", "p_idx":"PLUS"}
526 for k,v in list(a.items()):
527 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(20,20)))" % (k,v)
529 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
530 self.attr1 = wx.ListItemAttr()
531 self.attr1.SetBackgroundColour((230, 230, 230))
532 self.attr2 = wx.ListItemAttr()
533 self.attr2.SetBackgroundColour("light blue")
534 #self.attrselected = wx.ListItemAttr()
535 #self.attrselected.SetBackgroundColour("red")
539 for name in ['Categories'] + self.first :
540 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
542 self.itemDataMap = self.dlist
543 self.itemIndexMap = list(self.dlist.keys())
544 self.SetItemCount(len(self.dlist))
545 listmix.ListCtrlAutoWidthMixin.__init__(self)
546 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
548 #self.SortListItems(1, False)
549 self.SetColumnWidth(0, 300)
550 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
552 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
553 self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.ShowWords)
554 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnBeginEdit)
555 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit)
556 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
557 self.Bind(wx.EVT_LIST_COL_CLICK, self.OnSortColumn)
559 if self.GetItemCount() != 0 :
560 #self.SetItemState(0, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
563 dt = MyListDropCate(self)
564 self.SetDropTarget(dt)
566 def OnSortColumn(self, evt) :
567 print(self.currentItem)
570 def SetListFont(self) :
571 self.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
573 def OnGetItemImage(self, item):
576 def OnBeginEdit(self, event) :
577 self.EditLabel(event.GetIndex())
580 def OnEndEdit(self, event) :
581 newlabel = event.GetLabel()
582 idx = event.GetIndex()
583 oldlabel = self.GetItemText(idx)
584 if newlabel not in self.cate.cate['CATE'] :
585 self.cate.cate['CATE'][newlabel] = self.cate.cate['CATE'][oldlabel]
586 del(self.cate.cate['CATE'][oldlabel])
587 self.RefreshData(self.cate.getcate())
589 def ShowWords(self, event) :
590 index = event.GetIndex()
592 data = self.cate.getcatewords(self.GetItemText(index))
593 self.parent.m_listCateWords.RefreshData(data)
594 self.parent.m_listCateWords.SetSelection(0)
599 def RefreshData(self, data):
601 item = self.currentItem
604 self.itemDataMap = data
605 self.itemIndexMap = list(data.keys())
606 self.SetItemCount(len(data))
607 order = self._colSortFlag[self._col]
608 self.SortListItems(self._col, order)
609 #self.SetColumnWidth(0, wx.LIST_AUTOSIZE)
610 #self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
611 #self.SetColumnWidth(0,300)
615 self.SetSelection(item)
620 def GetListCtrl(self):
623 def GetSortImages(self):
624 return (self.sm_dn, self.sm_up)
626 def SortItems(self, sorter=None):
628 select = self.currentItem
629 word = self.GetItemData(select)[0]
630 except Exception as e: print('word',e)
632 listTemp = sorted(self.itemDataMap.items(),
633 key=lambda x:x[1][self._col], reverse= (self._colSortFlag[self._col]!=True))
634 dlist = dict([[line[0],line[1]] for line in listTemp])
635 self.itemDataMap = dlist
636 self.itemIndexMap = list(dlist.keys())
637 self.Refresh() # redraw the list
639 formes = [self.getColumnText(i, 0) for i in range(self.GetItemCount())]
640 idx = [i for i, val in enumerate(formes) if val == word][0]
641 self.SetSelection(idx)
643 except Exception as e: print(e)
645 def OnGetItemText(self, item, col):
646 index=self.itemIndexMap[item]
647 s = self.itemDataMap[index][col]
648 if isinstance(s, (int, float)):
651 return s #modification pour python 3
653 def OnGetItemAttr(self, item):
654 # if self.IsSelected(index) == True :
655 # print('selected', index)
656 index=self.itemIndexMap[item]
662 def getselectedwords(self) :
663 words = [self.getColumnText(self.GetFirstSelected(), 0)]
664 last = self.GetFirstSelected()
665 while self.GetNextSelected(last) != -1:
666 last = self.GetNextSelected(last)
667 words.append(self.getColumnText(last, 0))
671 return self.getselectedwords()[0]
673 def GetSelections(self):
674 return self.getselectedwords()
676 def getColumnText(self, index, col):
677 item = self.GetItem(index, col)
678 return item.GetText()
680 def GetItemData(self, item) :
681 index=self.itemIndexMap[item]
682 s = self.itemDataMap[index]
685 def OnItemSelected(self, event):
686 self.currentItem = event.GetIndex() #event.m_itemIndex
689 def SetSelection(self, index) :
690 for i in range(0, self.GetItemCount(), 1) :
692 self.Select(index, on=1)
694 def GetItemInfo(self, idx):
696 Collect all relevant data of a listitem, and put it in a list.
700 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
701 l.append(self.GetItemData(idx)) # Itemdata.
702 l.append(self.GetItemText(idx)) # Text first column.
703 for i in range(1, self.GetColumnCount()): # Possible extra columns.
704 l.append(self.GetItem(idx, i).GetText())
709 def StartDrag(self, event):
711 Put together a data object for drag-and-drop _from_ this list.
716 while True: # Find all the selected items and put them in a list.
717 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
720 l.append(self.GetItemInfo(idx))
722 # Pickle the items list.
723 itemdata = pickle.dumps(l, 1)
724 # Create our own data format and use it
725 # in a Custom data object.
726 ldata = wx.CustomDataObject("ListCtrlItems")
727 ldata.SetData(itemdata)
728 # Now make a data object for the item list.
729 data = wx.DataObjectComposite()
732 # Create drop source and begin drag-and-drop.
733 dropSource = wx.DropSource(self)
734 dropSource.SetData(data)
735 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
737 # If move, we want to remove the item from this list.
738 if res == wx.DragMove and l[0][-1] != 'cate' :
739 # It's possible we are dragging/dropping from this list to this list.
740 # In which case, the index we are removing may have changed...
742 # Find correct position.
743 l.reverse() # Delete all the items, starting with the last item.
745 pos = self.FindItem(i[0], i[2])
749 def Insert(self, x, y, seq):
751 Insert text at given x, y coordinates --- used with drag-and-drop.
754 # Find insertion point.
755 index, flags = self.HitTest((x, y))
757 if index == wx.NOT_FOUND: # Not clicked on an item.
758 if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
759 index = self.GetItemCount() # Append to end of list.
760 elif self.GetItemCount() > 0:
761 if y <= self.GetItemRect(0).y: # Clicked just above first item.
762 index = -1 # Append to top of list.
764 index = self.GetItemCount() + 1 # Append to end of list.
765 else: # Clicked on an item.
766 # Get bounding rectangle for the item the user is dropping over.
767 rect = self.GetItemRect(index)
769 # If the user is dropping into the lower half of the rect,
770 # we want to insert _after_ this item.
771 # Correct for the fact that there may be a heading involved.
772 #if y > rect.y - self.GetItemRect(0).y + rect.height/2:
774 print('Insert de ListForCate', index, flags)
775 word, eff = seq[0][1]
776 if seq[0][-1] == 'words' :
777 if index < self.GetItemCount() and index != -1 :
780 self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
782 index = self.GetItemCount()
783 if self.cate.addcatefromwordtocate(word, eff) :
786 dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
788 self.dlist = self.cate.getcate()
789 self.RefreshData(self.dlist)
790 self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
791 self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
792 for i in range(0, self.GetItemCount(), 1):
794 self.Select(index, on=1)
795 self.parent.butsave.SetBackgroundColour((255,0,0,255))
796 if seq[0][-1] == 'catewords' :
797 if index < self.GetItemCount() and index != -1 :
800 if word not in self.cate.cate['CATE'][self.GetItemData(index)[0]][1] :
801 self.cate.changewordcate(self.GetItemData(index)[0], word, eff)
802 self.parent.butsave.SetBackgroundColour((255,0,0,255))
804 index = self.GetItemCount()
805 if self.cate.addcatefromwordcate(word, eff) :
806 self.parent.butsave.SetBackgroundColour((255,0,0,255))
808 dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
809 #self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
810 self.dlist = self.cate.getcate()
811 self.RefreshData(self.dlist)
812 self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
813 #self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
814 self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(self.currentItem)[0]))
815 #self.SetSelection(index)
819 # for i in seq: # Insert the item data.
820 # idx = self.InsertItem(index, i[2])
821 # self.SetItemData(idx, i[1])
822 # for j in range(1, self.GetColumnCount()):
823 # try: # Target list can have more columns than source.
824 # self.SetItem(idx, j, i[2+j])
826 # pass # Ignore the extra columns.
829 class ListForWords(ListForCate) :
830 def __init__(self, parent, dlist = {}, first = []):
831 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
833 self.cate = self.parent.cate
834 self.dlist= self.cate.getwordstocate()
836 self.il = wx.ImageList(16, 16)
837 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION"}
838 for k,v in list(a.items()):
839 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
841 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
842 self.attr1 = wx.ListItemAttr()
843 self.attr1.SetBackgroundColour((230, 230, 230))
844 self.attr2 = wx.ListItemAttr()
845 self.attr2.SetBackgroundColour("light blue")
846 #self.attrselected = wx.ListItemAttr()
847 #self.attrselected.SetBackgroundColour("red")
851 for name in ['To categorize'] + self.first :
852 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
854 self.itemDataMap = self.dlist
855 self.itemIndexMap = list(self.dlist.keys())
856 self.SetItemCount(len(self.dlist))
857 listmix.ListCtrlAutoWidthMixin.__init__(self)
858 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
859 self.SetColumnWidth(0, 400)
860 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
862 self.SortListItems(1, False)
864 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
865 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnDClick)
866 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
868 dt = MyListDropCate(self)
869 self.SetDropTarget(dt)
871 def OnDClick(self, event) :
872 idx = event.GetIndex()
875 def OnItemSelected(self, event):
876 self.currentItem = event.GetIndex() #event.m_itemIndex
879 def OnGetItemImage(self, item):
882 def GetItemInfo(self, idx):
884 Collect all relevant data of a listitem, and put it in a list.
888 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
889 l.append(self.GetItemData(idx)) # Itemdata.
890 l.append(self.GetItemText(idx)) # Text first column.
891 for i in range(1, self.GetColumnCount()): # Possible extra columns.
892 l.append(self.GetItem(idx, i).GetText())
897 def StartDrag(self, event):
899 Put together a data object for drag-and-drop _from_ this list.
904 while True: # Find all the selected items and put them in a list.
905 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
908 l.append(self.GetItemInfo(idx))
910 # Pickle the items list.
911 itemdata = pickle.dumps(l, 1)
912 # Create our own data format and use it
913 # in a Custom data object.
914 ldata = wx.CustomDataObject("ListCtrlItems")
915 ldata.SetData(itemdata)
916 # Now make a data object for the item list.
917 data = wx.DataObjectComposite()
920 # Create drop source and begin drag-and-drop.
921 dropSource = wx.DropSource(self)
922 dropSource.SetData(data)
923 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
926 # If move, we want to remove the item from this list.
927 if res == wx.DragMove and l[0][-1] != 'words':
928 # It's possible we are dragging/dropping from this list to this list.
929 # In which case, the index we are removing may have changed...
931 # Find correct position.
932 l.reverse() # Delete all the items, starting with the last item.
934 pos = self.FindItem(i[0], i[2])
935 print('detruit : ',pos)
939 def Insert(self, x, y, seq):
941 Insert text at given x, y coordinates --- used with drag-and-drop.
944 # Find insertion point.
945 index, flags = self.HitTest((x, y))
947 if index == wx.NOT_FOUND: # Not clicked on an item.
948 if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
949 index = self.GetItemCount() # Append to end of list.
950 elif self.GetItemCount() > 0:
951 if y <= self.GetItemRect(0).y: # Clicked just above first item.
952 index = 0 # Append to top of list.
954 index = self.GetItemCount() + 1 # Append to end of list.
955 else: # Clicked on an item.
956 # Get bounding rectangle for the item the user is dropping over.
957 rect = self.GetItemRect(index)
959 # If the user is dropping into the lower half of the rect,
960 # we want to insert _after_ this item.
961 # Correct for the fact that there may be a heading involved.
962 if y > rect.y - self.GetItemRect(0).y + rect.height/2:
964 word, eff = seq[0][1]
965 if seq[0][-1] == 'catewords' :
968 categorie = self.cate.findcatefromword(word)
969 self.cate.addwordinwords(categorie, word, eff)
970 self.RefreshData(self.cate.getwordstocate())
971 self.parent.m_listCate.RefreshData(self.cate.getcate())
972 self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(categorie))
973 self.parent.butsave.SetBackgroundColour((255,0,0,255))
974 elif seq[0][-1] == 'cate' :
975 categorie = seq[0][1][0]
976 self.cate.delcate(categorie)
977 self.RefreshData(self.cate.getwordstocate())
978 self.parent.m_listCate.RefreshData(self.cate.getcate())
979 self.parent.m_listCate.SetSelection(0)
980 self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(self.parent.m_listCate.GetItemText(0)))
981 self.parent.butsave.SetBackgroundColour((255,0,0,255))
984 class ListForCateWords(ListForCate) :
985 def __init__(self, parent, dlist = {}, first = []):
986 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
988 self.cate = self.parent.cate
991 self.il = wx.ImageList(16, 16)
992 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","p_idx":"TIP","e_idx":"ERROR","i_idx":"QUESTION"}
993 for k,v in list(a.items()):
994 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
996 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
997 self.attr1 = wx.ListItemAttr()
998 self.attr1.SetBackgroundColour((230, 230, 230))
999 self.attr2 = wx.ListItemAttr()
1000 self.attr2.SetBackgroundColour("light blue")
1001 #self.attrselected = wx.ListItemAttr()
1002 #self.attrselected.SetBackgroundColour("red")
1006 for name in ['Contents'] + self.first :
1007 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
1009 self.itemDataMap = self.dlist
1010 self.itemIndexMap = list(self.dlist.keys())
1011 self.SetItemCount(len(self.dlist))
1012 listmix.ListCtrlAutoWidthMixin.__init__(self)
1013 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
1014 self.SetColumnWidth(0, 300)
1015 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
1017 self.SortListItems(1, False)
1019 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
1020 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1022 dt = MyListDropCate(self)
1023 self.SetDropTarget(dt)
1025 def OnItemSelected(self, event):
1026 self.currentItem = event.GetIndex() #event.m_itemIndex
1030 def GetItemInfo(self, idx):
1032 Collect all relevant data of a listitem, and put it in a list.
1036 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
1037 l.append(self.GetItemData(idx)) # Itemdata.
1038 l.append(self.GetItemText(idx)) # Text first column.
1039 for i in range(1, self.GetColumnCount()): # Possible extra columns.
1040 l.append(self.GetItem(idx, i).GetText())
1041 l.append('catewords')
1045 def StartDrag(self, event):
1047 Put together a data object for drag-and-drop _from_ this list.
1052 while True: # Find all the selected items and put them in a list.
1053 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
1056 l.append(self.GetItemInfo(idx))
1058 # Pickle the items list.
1059 itemdata = pickle.dumps(l, 1)
1060 # Create our own data format and use it
1061 # in a Custom data object.
1062 ldata = wx.CustomDataObject("ListCtrlItems")
1063 ldata.SetData(itemdata)
1064 # Now make a data object for the item list.
1065 data = wx.DataObjectComposite()
1068 # Create drop source and begin drag-and-drop.
1069 dropSource = wx.DropSource(self)
1070 dropSource.SetData(data)
1071 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
1073 print(self.parent.m_listCate.currentItem)
1075 # If move, we want to remove the item from this list.
1076 #if res == wx.DragMove:
1077 # # It's possible we are dragging/dropping from this list to this list.
1078 # # In which case, the index we are removing may have changed...
1080 # # Find correct position.
1081 # l.reverse() # Delete all the items, starting with the last item.
1083 # pos = self.FindItem(i[0], i[2])
1084 # self.DeleteItem(pos)
1087 def Insert(self, x, y, seq):
1089 Insert text at given x, y coordinates --- used with drag-and-drop.
1092 # Find insertion point.
1093 index, flags = self.HitTest((x, y))
1095 # if index == wx.NOT_FOUND: # Not clicked on an item.
1096 # if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
1097 # index = self.GetItemCount() # Append to end of list.
1098 # elif self.GetItemCount() > 0:
1099 # if y <= self.GetItemRect(0).y: # Clicked just above first item.
1100 # index = 0 # Append to top of list.
1102 # index = self.GetItemCount() + 1 # Append to end of list.
1103 # else: # Clicked on an item.
1104 # # Get bounding rectangle for the item the user is dropping over.
1105 # rect = self.GetItemRect(index)
1107 # # If the user is dropping into the lower half of the rect,
1108 # # we want to insert _after_ this item.
1109 # # Correct for the fact that there may be a heading involved.
1110 # if y > rect.y - self.GetItemRect(0).y + rect.height/2:
1112 print('Insert de ListForCateWords', index,flags)
1113 if seq[0][-1] == 'words' :
1116 categorie = self.parent.m_listCate.getColumnText(self.parent.m_listCate.GetFirstSelected(),0)
1117 self.cate.addwordincate(categorie, word, eff)
1118 self.dlist = self.cate.getwordstocate()
1119 self.RefreshData(self.cate.getcatewords(categorie))
1120 self.parent.m_listCate.RefreshData(self.cate.getcate())
1121 self.parent.m_listToCate.RefreshData(self.dlist)
1122 self.parent.butsave.SetBackgroundColour((255,0,0,255))
1125 class MyListDropCate(wx.DropTarget):
1127 Drop target for simple lists.
1129 def __init__(self, source):
1132 source: source listctrl.
1134 wx.DropTarget.__init__(self)
1142 # Specify the type of data we will accept.
1143 self.data = wx.CustomDataObject("ListCtrlItems")
1144 self.SetDataObject(self.data)
1146 #-----------------------------------------------------------------------
1148 # Called when OnDrop returns True.
1149 # We need to get the data and do something with it.
1150 def OnData(self, x, y, d):
1155 # Copy the data from the drag source to our data object.
1157 # Convert it back to a list and give it to the viewer.
1158 ldata = self.data.GetData()
1159 l = pickle.loads(ldata)
1160 self.dv.Insert(x, y, l)
1162 # What is returned signals the source what to do
1163 # with the original data (move, copy, etc.) In this
1164 # case we just return the suggested value given to us.