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()
358 panelwords = ListPanel(splitter, self, ListForWords)
359 splitter.AppendWindow(panelwords, splitsize)
360 panelcate = ListPanel(splitter, self, ListForCate)
361 splitter.AppendWindow(panelcate, splitsize)
362 panelwordscate = ListPanel(splitter, self, ListForCateWords)
363 splitter.AppendWindow(panelwordscate, splitsize)
364 self.m_listToCate = panelwords.list
365 self.m_listCate = panelcate.list
366 self.m_listCateWords = panelwordscate.list
369 bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
371 self.butsave = wx.Button( self, wx.ID_SAVE, u"Save", wx.DefaultPosition, wx.DefaultSize, 0 )
372 bSizer2.Add( self.butsave, 0, wx.ALL, 5 )
374 self.butcsv = wx.Button( self, wx.ID_ANY, u"Export Columns", wx.DefaultPosition, wx.DefaultSize, 0 )
375 bSizer2.Add( self.butcsv, 0, wx.ALL, 5 )
377 self.butdict = wx.Button( self, wx.ID_ANY, u"Export dictonary", wx.DefaultPosition, wx.DefaultSize, 0 )
378 bSizer2.Add( self.butdict, 0, wx.ALL, 5 )
380 self.butload = wx.Button( self, wx.ID_ANY, u"Load a categorization", wx.DefaultPosition, wx.DefaultSize, 0 )
381 bSizer2.Add( self.butload, 0, wx.ALL, 5 )
383 self.butaddcate = wx.Button( self, wx.ID_ANY, u"Add a category", wx.DefaultPosition, wx.DefaultSize, 0 )
384 bSizer2.Add( self.butaddcate, 0, wx.ALL, 5 )
387 bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
389 self.nbword = """Words : {:d} ({:d}) | """
391 self.stat = """ Words to categorize : {:d} ({}%) - {:d} ({}%) -- Categories : {:d} - {:d} ({}%) - {:d} ({}%)"""
392 for panel in [panelwords, panelcate, panelwordscate] :
393 panel.m_listToCate = self.m_listToCate
394 panel.m_listCate = self.m_listCate
395 panel.m_listCateWords = self.m_listCateWords
396 panel.butsave = self.butsave
398 # nbtocat, totocat, nbcate, totcate = self.cate.makestat()
399 # lenwords = self.cate.lenwords
400 # totwords = totocat + totcate
401 # prtocat = repr(nbtocat/lenwords)
402 # prtotocat = repr(totocat/totwords)
403 # prcate = repr(totcate/totwords)
404 self.wordtxt = wx.StaticText(self, -1, "")
405 bSizer3.Add( self.wordtxt, 0, wx.ALL, 5 )
406 self.stattxt = wx.StaticText(self, -1, "")
407 bSizer3.Add( self.stattxt, 0, wx.ALL, 5 )
410 gsizer.Add( bSizer2, 0, wx.EXPAND, 5 )
411 gsizer.Add( splitter, 2, wx.EXPAND, 5 )
412 gsizer.Add( bSizer3, 0, wx.EXPAND, 5 )
414 self.butsave.Bind(wx.EVT_BUTTON, self.OnSave)
415 self.butcsv.Bind(wx.EVT_BUTTON, self.OnCSV)
416 self.butdict.Bind(wx.EVT_BUTTON, self.OnDict)
417 self.butsave.SetBackgroundColour((14, 242, 14, 255))
418 self.butload.Bind(wx.EVT_BUTTON, self.OnLoad)
419 self.butaddcate.Bind(wx.EVT_BUTTON, self.OnAddCate)
421 self.SetSizer( gsizer )
429 def OnLoad(self, event) :
430 if len(self.cate.cate['CATE']) != 0 :
431 message = wx.MessageDialog(self, _("Categories must be empty to load a categorization."), _("Information"), wx.OK|wx.ICON_WARNING)
435 wildcard = "json|*.json|" \
438 self, message="Choose a file",
439 defaultDir=self.pathout.dirout,
443 wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST |
447 if dlg.ShowModal() == wx.ID_OK:
448 paths = dlg.GetPaths()
450 self.cate.loadcate(path)
451 self.m_listCate.RefreshData(self.cate.getcate())
452 self.m_listToCate.RefreshData(self.cate.getwordstocate())
455 def OnSave(self, event) :
457 self.butsave.SetBackgroundColour((14, 242, 14, 255))
459 def OnCSV(self, event) :
460 wordscate = self.cate.getwordscate()
461 newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
462 for line in self.tableau.select_col(self.tableau.selected_col):
465 newline.append(wordscate.get(word,word))
466 newtab.append(newline)
467 with open(self.pathout['tableout.csv'], 'w', encoding='utf8') as f :
468 f.write('\n'.join(['\t'.join(line) for line in newtab]))
469 message = wx.MessageDialog(self, _("Export successful\n%s" % self.pathout['tableout.csv']), _("Information"), wx.OK|wx.ICON_INFORMATION)
473 def OnDict(self, event):
474 with open(self.pathout['dictionnary.txt'], 'w', encoding='utf8') as f :
475 for categorie in self.cate.cate['CATE'] :
476 f.write(categorie + ': \t' + repr(self.cate.cate['CATE'][categorie][0]) + '\n')
477 for word in self.cate.cate['CATE'][categorie][1] :
478 f.write('\t' + word + ': \t' + repr(self.cate.cate['CATE'][categorie][1][word]) + '\n')
479 for word in self.cate.cate['TOCATE'] :
480 f.write(word + ':\t' + repr(self.cate.cate['TOCATE'][word]) + '\n')
481 message = wx.MessageDialog(self, _("Export successful\n%s" % self.pathout['dictionnary.txt']), _("Information"), wx.OK|wx.ICON_INFORMATION)
486 nbtocat, totocat, nbcate, totcate, lenwordincate = self.cate.makestat()
487 totwords = totocat + totcate
488 prtocat = repr(round((nbtocat/self.cate.lenwords) * 100 ,2))
489 prtotocat = repr(round((totocat/totwords) * 100, 2))
490 prcate = repr(round((totcate/totwords)*100, 2))
491 prwordincate = repr(round((lenwordincate/self.cate.lenwords)*100, 2))
492 self.stattxt.SetLabel(self.stat.format(nbtocat, prtocat, totocat, prtotocat, nbcate, lenwordincate, prwordincate, totcate, prcate))
495 def OnAddToTable(self) :
496 wordscate = self.cate.getwordscate()
497 newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
498 for line in self.tableau.select_col(self.tableau.selected_col):
501 newline.append(wordscate.get(word,word))
502 newtab.append(newline)
504 def OnAddCate(self, evt) :
505 print('add a category')
506 print(self.m_listCate.GetItemCount())
507 self.cate.addcatefromscratch()
508 self.m_listCate.dlist = self.cate.getcate()
509 self.m_listCate.RefreshData(self.m_listCate.dlist)
510 self.m_listCate.SetSelection(self.m_listCate.GetItemCount() - 1)
513 class ListForCate(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
515 def __init__(self, parent, dlist = {}, first = [], usefirst = False, menu = True):
516 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)
518 self.cate = self.parent.cate
519 self.dlist= self.cate.getcate()
521 self.il = wx.ImageList(20, 20)
522 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION", "p_idx":"PLUS"}
523 for k,v in list(a.items()):
524 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(20,20)))" % (k,v)
526 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
527 self.attr1 = wx.ListItemAttr()
528 self.attr1.SetBackgroundColour((230, 230, 230))
529 self.attr2 = wx.ListItemAttr()
530 self.attr2.SetBackgroundColour("light blue")
531 #self.attrselected = wx.ListItemAttr()
532 #self.attrselected.SetBackgroundColour("red")
536 for name in ['Categories'] + self.first :
537 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
539 self.itemDataMap = self.dlist
540 self.itemIndexMap = list(self.dlist.keys())
541 self.SetItemCount(len(self.dlist))
542 listmix.ListCtrlAutoWidthMixin.__init__(self)
543 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
545 #self.SortListItems(1, False)
546 self.SetColumnWidth(0, 300)
547 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
549 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
550 self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.ShowWords)
551 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnBeginEdit)
552 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit)
553 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
554 self.Bind(wx.EVT_LIST_COL_CLICK, self.OnSortColumn)
556 if self.GetItemCount() != 0 :
557 #self.SetItemState(0, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
560 dt = MyListDropCate(self)
561 self.SetDropTarget(dt)
563 def OnSortColumn(self, evt) :
564 print(self.currentItem)
567 def SetListFont(self) :
568 self.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
570 def OnGetItemImage(self, item):
573 def OnBeginEdit(self, event) :
574 self.EditLabel(event.GetIndex())
577 def OnEndEdit(self, event) :
578 newlabel = event.GetLabel()
579 idx = event.GetIndex()
580 oldlabel = self.GetItemText(idx)
581 if newlabel not in self.cate.cate['CATE'] :
582 self.cate.cate['CATE'][newlabel] = self.cate.cate['CATE'][oldlabel]
583 del(self.cate.cate['CATE'][oldlabel])
584 self.RefreshData(self.cate.getcate())
586 def ShowWords(self, event) :
587 index = event.GetIndex()
589 data = self.cate.getcatewords(self.GetItemText(index))
590 self.parent.m_listCateWords.RefreshData(data)
591 self.parent.m_listCateWords.SetSelection(0)
596 def RefreshData(self, data):
598 item = self.currentItem
601 self.itemDataMap = data
602 self.itemIndexMap = list(data.keys())
603 self.SetItemCount(len(data))
604 order = self._colSortFlag[self._col]
605 self.SortListItems(self._col, order)
606 #self.SetColumnWidth(0, wx.LIST_AUTOSIZE)
607 #self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
608 #self.SetColumnWidth(0,300)
612 self.SetSelection(item)
617 def GetListCtrl(self):
620 def GetSortImages(self):
621 return (self.sm_dn, self.sm_up)
623 def SortItems(self, sorter=None):
625 select = self.currentItem
626 word = self.GetItemData(select)[0]
627 except Exception as e: print('word',e)
629 listTemp = sorted(self.itemDataMap.items(),
630 key=lambda x:x[1][self._col], reverse= (self._colSortFlag[self._col]!=True))
631 dlist = dict([[line[0],line[1]] for line in listTemp])
632 self.itemDataMap = dlist
633 self.itemIndexMap = list(dlist.keys())
634 self.Refresh() # redraw the list
636 formes = [self.getColumnText(i, 0) for i in range(self.GetItemCount())]
637 idx = [i for i, val in enumerate(formes) if val == word][0]
638 self.SetSelection(idx)
640 except Exception as e: print(e)
642 def OnGetItemText(self, item, col):
643 index=self.itemIndexMap[item]
644 s = self.itemDataMap[index][col]
645 if isinstance(s, (int, float)):
648 return s #modification pour python 3
650 def OnGetItemAttr(self, item):
651 # if self.IsSelected(index) == True :
652 # print('selected', index)
653 index=self.itemIndexMap[item]
659 def getselectedwords(self) :
660 words = [self.getColumnText(self.GetFirstSelected(), 0)]
661 last = self.GetFirstSelected()
662 while self.GetNextSelected(last) != -1:
663 last = self.GetNextSelected(last)
664 words.append(self.getColumnText(last, 0))
668 return self.getselectedwords()[0]
670 def GetSelections(self):
671 return self.getselectedwords()
673 def getColumnText(self, index, col):
674 item = self.GetItem(index, col)
675 return item.GetText()
677 def GetItemData(self, item) :
678 index=self.itemIndexMap[item]
679 s = self.itemDataMap[index]
682 def OnItemSelected(self, event):
683 self.currentItem = event.GetIndex() #event.m_itemIndex
686 def SetSelection(self, index) :
687 for i in range(0, self.GetItemCount(), 1) :
689 self.Select(index, on=1)
691 def GetItemInfo(self, idx):
693 Collect all relevant data of a listitem, and put it in a list.
697 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
698 l.append(self.GetItemData(idx)) # Itemdata.
699 l.append(self.GetItemText(idx)) # Text first column.
700 for i in range(1, self.GetColumnCount()): # Possible extra columns.
701 l.append(self.GetItem(idx, i).GetText())
706 def StartDrag(self, event):
708 Put together a data object for drag-and-drop _from_ this list.
713 while True: # Find all the selected items and put them in a list.
714 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
717 l.append(self.GetItemInfo(idx))
719 # Pickle the items list.
720 itemdata = pickle.dumps(l, 1)
721 # Create our own data format and use it
722 # in a Custom data object.
723 ldata = wx.CustomDataObject("ListCtrlItems")
724 ldata.SetData(itemdata)
725 # Now make a data object for the item list.
726 data = wx.DataObjectComposite()
729 # Create drop source and begin drag-and-drop.
730 dropSource = wx.DropSource(self)
731 dropSource.SetData(data)
732 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
734 # If move, we want to remove the item from this list.
735 if res == wx.DragMove and l[0][-1] != 'cate' :
736 # It's possible we are dragging/dropping from this list to this list.
737 # In which case, the index we are removing may have changed...
739 # Find correct position.
740 l.reverse() # Delete all the items, starting with the last item.
742 pos = self.FindItem(i[0], i[2])
746 def Insert(self, x, y, seq):
748 Insert text at given x, y coordinates --- used with drag-and-drop.
751 # Find insertion point.
752 index, flags = self.HitTest((x, y))
754 if index == wx.NOT_FOUND: # Not clicked on an item.
755 if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
756 index = self.GetItemCount() # Append to end of list.
757 elif self.GetItemCount() > 0:
758 if y <= self.GetItemRect(0).y: # Clicked just above first item.
759 index = -1 # Append to top of list.
761 index = self.GetItemCount() + 1 # Append to end of list.
762 else: # Clicked on an item.
763 # Get bounding rectangle for the item the user is dropping over.
764 rect = self.GetItemRect(index)
766 # If the user is dropping into the lower half of the rect,
767 # we want to insert _after_ this item.
768 # Correct for the fact that there may be a heading involved.
769 #if y > rect.y - self.GetItemRect(0).y + rect.height/2:
771 print('Insert de ListForCate', index, flags)
772 word, eff = seq[0][1]
773 if seq[0][-1] == 'words' :
774 if index < self.GetItemCount() and index != -1 :
777 self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
779 index = self.GetItemCount()
780 if self.cate.addcatefromwordtocate(word, eff) :
783 dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
785 self.dlist = self.cate.getcate()
786 self.RefreshData(self.dlist)
787 self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
788 self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
789 for i in range(0, self.GetItemCount(), 1):
791 self.Select(index, on=1)
792 self.parent.butsave.SetBackgroundColour((255,0,0,255))
793 if seq[0][-1] == 'catewords' :
794 if index < self.GetItemCount() and index != -1 :
797 if word not in self.cate.cate['CATE'][self.GetItemData(index)[0]][1] :
798 self.cate.changewordcate(self.GetItemData(index)[0], word, eff)
799 self.parent.butsave.SetBackgroundColour((255,0,0,255))
801 index = self.GetItemCount()
802 if self.cate.addcatefromwordcate(word, eff) :
803 self.parent.butsave.SetBackgroundColour((255,0,0,255))
805 dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
806 #self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
807 self.dlist = self.cate.getcate()
808 self.RefreshData(self.dlist)
809 self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
810 #self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
811 self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(self.currentItem)[0]))
812 #self.SetSelection(index)
816 # for i in seq: # Insert the item data.
817 # idx = self.InsertItem(index, i[2])
818 # self.SetItemData(idx, i[1])
819 # for j in range(1, self.GetColumnCount()):
820 # try: # Target list can have more columns than source.
821 # self.SetItem(idx, j, i[2+j])
823 # pass # Ignore the extra columns.
826 class ListForWords(ListForCate) :
827 def __init__(self, parent, dlist = {}, first = []):
828 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
830 self.cate = self.parent.cate
831 self.dlist= self.cate.getwordstocate()
833 self.il = wx.ImageList(16, 16)
834 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION"}
835 for k,v in list(a.items()):
836 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
838 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
839 self.attr1 = wx.ListItemAttr()
840 self.attr1.SetBackgroundColour((230, 230, 230))
841 self.attr2 = wx.ListItemAttr()
842 self.attr2.SetBackgroundColour("light blue")
843 #self.attrselected = wx.ListItemAttr()
844 #self.attrselected.SetBackgroundColour("red")
848 for name in ['To categorize'] + self.first :
849 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
851 self.itemDataMap = self.dlist
852 self.itemIndexMap = list(self.dlist.keys())
853 self.SetItemCount(len(self.dlist))
854 listmix.ListCtrlAutoWidthMixin.__init__(self)
855 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
856 self.SetColumnWidth(0, 400)
857 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
859 self.SortListItems(1, False)
861 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
862 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnDClick)
863 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
865 dt = MyListDropCate(self)
866 self.SetDropTarget(dt)
868 def OnDClick(self, event) :
869 idx = event.GetIndex()
872 def OnItemSelected(self, event):
873 self.currentItem = event.GetIndex() #event.m_itemIndex
876 def OnGetItemImage(self, item):
879 def GetItemInfo(self, idx):
881 Collect all relevant data of a listitem, and put it in a list.
885 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
886 l.append(self.GetItemData(idx)) # Itemdata.
887 l.append(self.GetItemText(idx)) # Text first column.
888 for i in range(1, self.GetColumnCount()): # Possible extra columns.
889 l.append(self.GetItem(idx, i).GetText())
894 def StartDrag(self, event):
896 Put together a data object for drag-and-drop _from_ this list.
901 while True: # Find all the selected items and put them in a list.
902 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
905 l.append(self.GetItemInfo(idx))
907 # Pickle the items list.
908 itemdata = pickle.dumps(l, 1)
909 # Create our own data format and use it
910 # in a Custom data object.
911 ldata = wx.CustomDataObject("ListCtrlItems")
912 ldata.SetData(itemdata)
913 # Now make a data object for the item list.
914 data = wx.DataObjectComposite()
917 # Create drop source and begin drag-and-drop.
918 dropSource = wx.DropSource(self)
919 dropSource.SetData(data)
920 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
923 # If move, we want to remove the item from this list.
924 if res == wx.DragMove and l[0][-1] != 'words':
925 # It's possible we are dragging/dropping from this list to this list.
926 # In which case, the index we are removing may have changed...
928 # Find correct position.
929 l.reverse() # Delete all the items, starting with the last item.
931 pos = self.FindItem(i[0], i[2])
932 print('detruit : ',pos)
936 def Insert(self, x, y, seq):
938 Insert text at given x, y coordinates --- used with drag-and-drop.
941 # Find insertion point.
942 index, flags = self.HitTest((x, y))
944 if index == wx.NOT_FOUND: # Not clicked on an item.
945 if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
946 index = self.GetItemCount() # Append to end of list.
947 elif self.GetItemCount() > 0:
948 if y <= self.GetItemRect(0).y: # Clicked just above first item.
949 index = 0 # Append to top of list.
951 index = self.GetItemCount() + 1 # Append to end of list.
952 else: # Clicked on an item.
953 # Get bounding rectangle for the item the user is dropping over.
954 rect = self.GetItemRect(index)
956 # If the user is dropping into the lower half of the rect,
957 # we want to insert _after_ this item.
958 # Correct for the fact that there may be a heading involved.
959 if y > rect.y - self.GetItemRect(0).y + rect.height/2:
961 word, eff = seq[0][1]
962 if seq[0][-1] == 'catewords' :
965 categorie = self.cate.findcatefromword(word)
966 self.cate.addwordinwords(categorie, word, eff)
967 self.RefreshData(self.cate.getwordstocate())
968 self.parent.m_listCate.RefreshData(self.cate.getcate())
969 self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(categorie))
970 self.parent.butsave.SetBackgroundColour((255,0,0,255))
971 elif seq[0][-1] == 'cate' :
972 categorie = seq[0][1][0]
973 self.cate.delcate(categorie)
974 self.RefreshData(self.cate.getwordstocate())
975 self.parent.m_listCate.RefreshData(self.cate.getcate())
976 self.parent.m_listCate.SetSelection(0)
977 self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(self.parent.m_listCate.GetItemText(0)))
978 self.parent.butsave.SetBackgroundColour((255,0,0,255))
981 class ListForCateWords(ListForCate) :
982 def __init__(self, parent, dlist = {}, first = []):
983 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
985 self.cate = self.parent.cate
988 self.il = wx.ImageList(16, 16)
989 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","p_idx":"TIP","e_idx":"ERROR","i_idx":"QUESTION"}
990 for k,v in list(a.items()):
991 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
993 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
994 self.attr1 = wx.ListItemAttr()
995 self.attr1.SetBackgroundColour((230, 230, 230))
996 self.attr2 = wx.ListItemAttr()
997 self.attr2.SetBackgroundColour("light blue")
998 #self.attrselected = wx.ListItemAttr()
999 #self.attrselected.SetBackgroundColour("red")
1003 for name in ['Contents'] + self.first :
1004 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
1006 self.itemDataMap = self.dlist
1007 self.itemIndexMap = list(self.dlist.keys())
1008 self.SetItemCount(len(self.dlist))
1009 listmix.ListCtrlAutoWidthMixin.__init__(self)
1010 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
1011 self.SetColumnWidth(0, 300)
1012 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
1014 self.SortListItems(1, False)
1016 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
1017 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1019 dt = MyListDropCate(self)
1020 self.SetDropTarget(dt)
1022 def OnItemSelected(self, event):
1023 self.currentItem = event.GetIndex() #event.m_itemIndex
1027 def GetItemInfo(self, idx):
1029 Collect all relevant data of a listitem, and put it in a list.
1033 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
1034 l.append(self.GetItemData(idx)) # Itemdata.
1035 l.append(self.GetItemText(idx)) # Text first column.
1036 for i in range(1, self.GetColumnCount()): # Possible extra columns.
1037 l.append(self.GetItem(idx, i).GetText())
1038 l.append('catewords')
1042 def StartDrag(self, event):
1044 Put together a data object for drag-and-drop _from_ this list.
1049 while True: # Find all the selected items and put them in a list.
1050 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
1053 l.append(self.GetItemInfo(idx))
1055 # Pickle the items list.
1056 itemdata = pickle.dumps(l, 1)
1057 # Create our own data format and use it
1058 # in a Custom data object.
1059 ldata = wx.CustomDataObject("ListCtrlItems")
1060 ldata.SetData(itemdata)
1061 # Now make a data object for the item list.
1062 data = wx.DataObjectComposite()
1065 # Create drop source and begin drag-and-drop.
1066 dropSource = wx.DropSource(self)
1067 dropSource.SetData(data)
1068 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
1070 print(self.parent.m_listCate.currentItem)
1072 # If move, we want to remove the item from this list.
1073 #if res == wx.DragMove:
1074 # # It's possible we are dragging/dropping from this list to this list.
1075 # # In which case, the index we are removing may have changed...
1077 # # Find correct position.
1078 # l.reverse() # Delete all the items, starting with the last item.
1080 # pos = self.FindItem(i[0], i[2])
1081 # self.DeleteItem(pos)
1084 def Insert(self, x, y, seq):
1086 Insert text at given x, y coordinates --- used with drag-and-drop.
1089 # Find insertion point.
1090 index, flags = self.HitTest((x, y))
1092 # if index == wx.NOT_FOUND: # Not clicked on an item.
1093 # if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
1094 # index = self.GetItemCount() # Append to end of list.
1095 # elif self.GetItemCount() > 0:
1096 # if y <= self.GetItemRect(0).y: # Clicked just above first item.
1097 # index = 0 # Append to top of list.
1099 # index = self.GetItemCount() + 1 # Append to end of list.
1100 # else: # Clicked on an item.
1101 # # Get bounding rectangle for the item the user is dropping over.
1102 # rect = self.GetItemRect(index)
1104 # # If the user is dropping into the lower half of the rect,
1105 # # we want to insert _after_ this item.
1106 # # Correct for the fact that there may be a heading involved.
1107 # if y > rect.y - self.GetItemRect(0).y + rect.height/2:
1109 print('Insert de ListForCateWords', index,flags)
1110 if seq[0][-1] == 'words' :
1113 categorie = self.parent.m_listCate.getColumnText(self.parent.m_listCate.GetFirstSelected(),0)
1114 self.cate.addwordincate(categorie, word, eff)
1115 self.dlist = self.cate.getwordstocate()
1116 self.RefreshData(self.cate.getcatewords(categorie))
1117 self.parent.m_listCate.RefreshData(self.cate.getcate())
1118 self.parent.m_listToCate.RefreshData(self.dlist)
1119 self.parent.butsave.SetBackgroundColour((255,0,0,255))
1122 class MyListDropCate(wx.DropTarget):
1124 Drop target for simple lists.
1126 def __init__(self, source):
1129 source: source listctrl.
1131 wx.DropTarget.__init__(self)
1139 # Specify the type of data we will accept.
1140 self.data = wx.CustomDataObject("ListCtrlItems")
1141 self.SetDataObject(self.data)
1143 #-----------------------------------------------------------------------
1145 # Called when OnDrop returns True.
1146 # We need to get the data and do something with it.
1147 def OnData(self, x, y, d):
1152 # Copy the data from the drag source to our data object.
1154 # Convert it back to a list and give it to the viewer.
1155 ldata = self.data.GetData()
1156 l = pickle.loads(ldata)
1157 self.dv.Insert(x, y, l)
1159 # What is returned signals the source what to do
1160 # with the original data (move, copy, etc.) In this
1161 # case we just return the suggested value given to us.