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
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 )
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)
240 wildcard = "json|*.json|" \
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)
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)
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)
321 # self.parent = parent
322 # self.cate = gparent.cate
323 # self.list = List(self, dlist = gparent.cate, first = ['eff'])
326 #class ElCategorizator ( wx.Panel ):
328 # 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 ):
329 # wx.Panel.__init__ ( self, parent, id = id, pos = pos, size = size, style = style, name = name )
330 # self.pathout = pathout
331 # self.parent = parent
332 # self.tableau = tableau
334 # self.cate = CategoDict(self.pathout)
336 # splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
337 # self.splitter = splitter
338 # sizer = wx.BoxSizer(wx.HORIZONTAL)
339 # sizer.Add(splitter, 1, wx.EXPAND)
340 # self.SetSizer(sizer)
342 # panelwords = ListPanel(splitter, self, ListForWords)
343 # splitter.AppendWindow(panelwords, 150)
344 # panelcate = ListPanel(splitter, self, ListForCate)
345 # splitter.AppendWindow(panelcate, 150)
346 # panelwordscate = ListPanel(splitter, self, ListForCateWords)
347 # splitter.AppendWindow(panelwordscate, 150)
348 # self.m_listToCate = panelwords.list
349 # self.m_listCate = panelcate.list
350 # self.m_listCateWords = panelwordscate.list
352 # def __del__( self ):
355 # def OnSave(self, event) :
357 # self.butsave.SetBackgroundColour((14, 242, 14, 255))
359 # def OnCSV(self, event) :
360 # wordscate = self.cate.getwordscate()
361 # newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
362 # for line in self.tableau.select_col(self.tableau.selected_col):
365 # newline.append(wordscate.get(word,word))
366 # newtab.append(newline)
367 # with open(self.pathout['tableout.csv'], 'w') as f :
368 # f.write('\n'.join(['\t'.join(line) for line in newtab]))
369 # print("csv exported !")
371 # def OnDict(self, event):
372 # with open(self.pathout['dictionnary.txt'], 'w') as f :
373 # for categorie in self.cate.cate['CATE'] :
374 # f.write(categorie + ': \t' + repr(self.cate.cate['CATE'][categorie][0]) + '\n')
375 # for word in self.cate.cate['CATE'][categorie][1] :
376 # f.write('\t' + word + ': \t' + repr(self.cate.cate['CATE'][categorie][1][word]) + '\n')
377 # for word in self.cate.cate['TOCATE'] :
378 # f.write(word + ':\t' + repr(self.cate.cate['TOCATE'][word]) + '\n')
379 # print("dictionnary exported !")
382 class ListForCate(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
384 def __init__(self, parent, dlist = {}, first = [], usefirst = False, menu = True):
385 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)
387 self.cate = self.parent.cate
388 self.dlist= self.cate.getcate()
390 self.il = wx.ImageList(20, 20)
391 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION", "p_idx":"PLUS"}
392 for k,v in list(a.items()):
393 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(20,20)))" % (k,v)
395 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
396 self.attr1 = wx.ListItemAttr()
397 self.attr1.SetBackgroundColour((230, 230, 230))
398 self.attr2 = wx.ListItemAttr()
399 self.attr2.SetBackgroundColour("light blue")
400 #self.attrselected = wx.ListItemAttr()
401 #self.attrselected.SetBackgroundColour("red")
405 for name in ['Categories'] + self.first :
406 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
408 self.itemDataMap = self.dlist
409 self.itemIndexMap = list(self.dlist.keys())
410 self.SetItemCount(len(self.dlist))
411 listmix.ListCtrlAutoWidthMixin.__init__(self)
412 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
414 #self.SortListItems(1, False)
415 self.SetColumnWidth(0, 300)
416 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
418 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
419 self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.ShowWords)
420 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnBeginEdit)
421 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit)
422 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
423 self.Bind(wx.EVT_LIST_COL_CLICK, self.OnSortColumn)
425 if self.GetItemCount() != 0 :
426 #self.SetItemState(0, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
429 dt = MyListDropCate(self)
430 self.SetDropTarget(dt)
432 def OnSortColumn(self, evt) :
433 print(self.currentItem)
436 def SetListFont(self) :
437 self.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
439 def OnGetItemImage(self, item):
442 def OnBeginEdit(self, event) :
443 self.EditLabel(event.GetIndex())
446 def OnEndEdit(self, event) :
447 newlabel = event.GetLabel()
448 idx = event.GetIndex()
449 oldlabel = self.GetItemText(idx)
450 if newlabel not in self.cate.cate['CATE'] :
451 self.cate.cate['CATE'][newlabel] = self.cate.cate['CATE'][oldlabel]
452 del(self.cate.cate['CATE'][oldlabel])
453 self.RefreshData(self.cate.getcate())
455 def ShowWords(self, event) :
456 index = event.GetIndex()
458 data = self.cate.getcatewords(self.GetItemText(index))
459 self.parent.m_listCateWords.RefreshData(data)
460 self.parent.m_listCateWords.SetSelection(0)
465 def RefreshData(self, data):
467 item = self.currentItem
470 self.itemDataMap = data
471 self.itemIndexMap = list(data.keys())
472 self.SetItemCount(len(data))
473 order = self._colSortFlag[self._col]
474 self.SortListItems(self._col, order)
475 #self.SetColumnWidth(0, wx.LIST_AUTOSIZE)
476 #self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
477 #self.SetColumnWidth(0,300)
481 self.SetSelection(item)
486 def GetListCtrl(self):
489 def GetSortImages(self):
490 return (self.sm_dn, self.sm_up)
492 def SortItems(self, sorter=None):
494 select = self.currentItem
495 word = self.GetItemData(select)[0]
496 except Exception as e: print('word',e)
498 listTemp = sorted(self.itemDataMap.items(),
499 key=lambda x:x[1][self._col], reverse= (self._colSortFlag[self._col]!=True))
500 dlist = dict([[line[0],line[1]] for line in listTemp])
501 self.itemDataMap = dlist
502 self.itemIndexMap = list(dlist.keys())
503 self.Refresh() # redraw the list
505 formes = [self.getColumnText(i, 0) for i in range(self.GetItemCount())]
506 idx = [i for i, val in enumerate(formes) if val == word][0]
507 self.SetSelection(idx)
509 except Exception as e: print(e)
511 def OnGetItemText(self, item, col):
512 index=self.itemIndexMap[item]
513 s = self.itemDataMap[index][col]
514 if isinstance(s, (int, float)):
517 return s #modification pour python 3
519 def OnGetItemAttr(self, item):
520 # if self.IsSelected(index) == True :
521 # print('selected', index)
522 index=self.itemIndexMap[item]
528 def getselectedwords(self) :
529 words = [self.getColumnText(self.GetFirstSelected(), 0)]
530 last = self.GetFirstSelected()
531 while self.GetNextSelected(last) != -1:
532 last = self.GetNextSelected(last)
533 words.append(self.getColumnText(last, 0))
537 return self.getselectedwords()[0]
539 def GetSelections(self):
540 return self.getselectedwords()
542 def getColumnText(self, index, col):
543 item = self.GetItem(index, col)
544 return item.GetText()
546 def GetItemData(self, item) :
547 index=self.itemIndexMap[item]
548 s = self.itemDataMap[index]
551 def OnItemSelected(self, event):
552 self.currentItem = event.GetIndex() #event.m_itemIndex
555 def SetSelection(self, index) :
556 for i in range(0, self.GetItemCount(), 1) :
558 self.Select(index, on=1)
560 def GetItemInfo(self, idx):
562 Collect all relevant data of a listitem, and put it in a list.
566 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
567 l.append(self.GetItemData(idx)) # Itemdata.
568 l.append(self.GetItemText(idx)) # Text first column.
569 for i in range(1, self.GetColumnCount()): # Possible extra columns.
570 l.append(self.GetItem(idx, i).GetText())
575 def StartDrag(self, event):
577 Put together a data object for drag-and-drop _from_ this list.
582 while True: # Find all the selected items and put them in a list.
583 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
586 l.append(self.GetItemInfo(idx))
588 # Pickle the items list.
589 itemdata = pickle.dumps(l, 1)
590 # Create our own data format and use it
591 # in a Custom data object.
592 ldata = wx.CustomDataObject("ListCtrlItems")
593 ldata.SetData(itemdata)
594 # Now make a data object for the item list.
595 data = wx.DataObjectComposite()
598 # Create drop source and begin drag-and-drop.
599 dropSource = wx.DropSource(self)
600 dropSource.SetData(data)
601 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
603 # If move, we want to remove the item from this list.
604 if res == wx.DragMove and l[0][-1] != 'cate' :
605 # It's possible we are dragging/dropping from this list to this list.
606 # In which case, the index we are removing may have changed...
608 # Find correct position.
609 l.reverse() # Delete all the items, starting with the last item.
611 pos = self.FindItem(i[0], i[2])
615 def Insert(self, x, y, seq):
617 Insert text at given x, y coordinates --- used with drag-and-drop.
620 # Find insertion point.
621 index, flags = self.HitTest((x, y))
623 if index == wx.NOT_FOUND: # Not clicked on an item.
624 if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
625 index = self.GetItemCount() # Append to end of list.
626 elif self.GetItemCount() > 0:
627 if y <= self.GetItemRect(0).y: # Clicked just above first item.
628 index = -1 # Append to top of list.
630 index = self.GetItemCount() + 1 # Append to end of list.
631 else: # Clicked on an item.
632 # Get bounding rectangle for the item the user is dropping over.
633 rect = self.GetItemRect(index)
635 # If the user is dropping into the lower half of the rect,
636 # we want to insert _after_ this item.
637 # Correct for the fact that there may be a heading involved.
638 #if y > rect.y - self.GetItemRect(0).y + rect.height/2:
640 print('Insert de ListForCate', index, flags)
641 word, eff = seq[0][1]
642 if seq[0][-1] == 'words' :
643 if index < self.GetItemCount() and index != -1 :
646 self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
648 index = self.GetItemCount()
649 if self.cate.addcatefromwordtocate(word, eff) :
652 dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
654 self.dlist = self.cate.getcate()
655 self.RefreshData(self.dlist)
656 self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
657 self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
658 for i in range(0, self.GetItemCount(), 1):
660 self.Select(index, on=1)
661 self.parent.butsave.SetBackgroundColour((255,0,0,255))
662 if seq[0][-1] == 'catewords' :
663 if index < self.GetItemCount() and index != -1 :
666 if word not in self.cate.cate['CATE'][self.GetItemData(index)[0]][1] :
667 self.cate.changewordcate(self.GetItemData(index)[0], word, eff)
668 self.parent.butsave.SetBackgroundColour((255,0,0,255))
670 index = self.GetItemCount()
671 if self.cate.addcatefromwordcate(word, eff) :
672 self.parent.butsave.SetBackgroundColour((255,0,0,255))
674 dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
675 #self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
676 self.dlist = self.cate.getcate()
677 self.RefreshData(self.dlist)
678 self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
679 #self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
680 self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(self.currentItem)[0]))
681 #self.SetSelection(index)
685 # for i in seq: # Insert the item data.
686 # idx = self.InsertItem(index, i[2])
687 # self.SetItemData(idx, i[1])
688 # for j in range(1, self.GetColumnCount()):
689 # try: # Target list can have more columns than source.
690 # self.SetItem(idx, j, i[2+j])
692 # pass # Ignore the extra columns.
695 class ListForWords(ListForCate) :
696 def __init__(self, parent, dlist = {}, first = []):
697 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
699 self.cate = self.parent.cate
700 self.dlist= self.cate.getwordstocate()
702 self.il = wx.ImageList(16, 16)
703 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION"}
704 for k,v in list(a.items()):
705 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
707 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
708 self.attr1 = wx.ListItemAttr()
709 self.attr1.SetBackgroundColour((230, 230, 230))
710 self.attr2 = wx.ListItemAttr()
711 self.attr2.SetBackgroundColour("light blue")
712 #self.attrselected = wx.ListItemAttr()
713 #self.attrselected.SetBackgroundColour("red")
717 for name in ['To categorize'] + self.first :
718 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
720 self.itemDataMap = self.dlist
721 self.itemIndexMap = list(self.dlist.keys())
722 self.SetItemCount(len(self.dlist))
723 listmix.ListCtrlAutoWidthMixin.__init__(self)
724 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
725 self.SetColumnWidth(0, 400)
726 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
728 self.SortListItems(1, False)
730 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
731 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnDClick)
732 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
734 dt = MyListDropCate(self)
735 self.SetDropTarget(dt)
737 def OnDClick(self, event) :
738 idx = event.GetIndex()
741 def OnItemSelected(self, event):
742 self.currentItem = event.GetIndex() #event.m_itemIndex
745 def OnGetItemImage(self, item):
748 def GetItemInfo(self, idx):
750 Collect all relevant data of a listitem, and put it in a list.
754 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
755 l.append(self.GetItemData(idx)) # Itemdata.
756 l.append(self.GetItemText(idx)) # Text first column.
757 for i in range(1, self.GetColumnCount()): # Possible extra columns.
758 l.append(self.GetItem(idx, i).GetText())
763 def StartDrag(self, event):
765 Put together a data object for drag-and-drop _from_ this list.
770 while True: # Find all the selected items and put them in a list.
771 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
774 l.append(self.GetItemInfo(idx))
776 # Pickle the items list.
777 itemdata = pickle.dumps(l, 1)
778 # Create our own data format and use it
779 # in a Custom data object.
780 ldata = wx.CustomDataObject("ListCtrlItems")
781 ldata.SetData(itemdata)
782 # Now make a data object for the item list.
783 data = wx.DataObjectComposite()
786 # Create drop source and begin drag-and-drop.
787 dropSource = wx.DropSource(self)
788 dropSource.SetData(data)
789 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
792 # If move, we want to remove the item from this list.
793 if res == wx.DragMove and l[0][-1] != 'words':
794 # It's possible we are dragging/dropping from this list to this list.
795 # In which case, the index we are removing may have changed...
797 # Find correct position.
798 l.reverse() # Delete all the items, starting with the last item.
800 pos = self.FindItem(i[0], i[2])
801 print('detruit : ',pos)
805 def Insert(self, x, y, seq):
807 Insert text at given x, y coordinates --- used with drag-and-drop.
810 # Find insertion point.
811 index, flags = self.HitTest((x, y))
813 if index == wx.NOT_FOUND: # Not clicked on an item.
814 if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
815 index = self.GetItemCount() # Append to end of list.
816 elif self.GetItemCount() > 0:
817 if y <= self.GetItemRect(0).y: # Clicked just above first item.
818 index = 0 # Append to top of list.
820 index = self.GetItemCount() + 1 # Append to end of list.
821 else: # Clicked on an item.
822 # Get bounding rectangle for the item the user is dropping over.
823 rect = self.GetItemRect(index)
825 # If the user is dropping into the lower half of the rect,
826 # we want to insert _after_ this item.
827 # Correct for the fact that there may be a heading involved.
828 if y > rect.y - self.GetItemRect(0).y + rect.height/2:
830 word, eff = seq[0][1]
831 if seq[0][-1] == 'catewords' :
834 categorie = self.cate.findcatefromword(word)
835 self.cate.addwordinwords(categorie, word, eff)
836 self.RefreshData(self.cate.getwordstocate())
837 self.parent.m_listCate.RefreshData(self.cate.getcate())
838 self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(categorie))
839 self.parent.butsave.SetBackgroundColour((255,0,0,255))
840 elif seq[0][-1] == 'cate' :
841 categorie = seq[0][1][0]
842 self.cate.delcate(categorie)
843 self.RefreshData(self.cate.getwordstocate())
844 self.parent.m_listCate.RefreshData(self.cate.getcate())
845 self.parent.m_listCate.SetSelection(0)
846 self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(self.parent.m_listCate.GetItemText(0)))
847 self.parent.butsave.SetBackgroundColour((255,0,0,255))
850 class ListForCateWords(ListForCate) :
851 def __init__(self, parent, dlist = {}, first = []):
852 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
854 self.cate = self.parent.cate
857 self.il = wx.ImageList(16, 16)
858 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","p_idx":"TIP","e_idx":"ERROR","i_idx":"QUESTION"}
859 for k,v in list(a.items()):
860 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
862 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
863 self.attr1 = wx.ListItemAttr()
864 self.attr1.SetBackgroundColour((230, 230, 230))
865 self.attr2 = wx.ListItemAttr()
866 self.attr2.SetBackgroundColour("light blue")
867 #self.attrselected = wx.ListItemAttr()
868 #self.attrselected.SetBackgroundColour("red")
872 for name in ['Contents'] + self.first :
873 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
875 self.itemDataMap = self.dlist
876 self.itemIndexMap = list(self.dlist.keys())
877 self.SetItemCount(len(self.dlist))
878 listmix.ListCtrlAutoWidthMixin.__init__(self)
879 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
880 self.SetColumnWidth(0, 300)
881 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
883 self.SortListItems(1, False)
885 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
886 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
888 dt = MyListDropCate(self)
889 self.SetDropTarget(dt)
891 def OnItemSelected(self, event):
892 self.currentItem = event.GetIndex() #event.m_itemIndex
896 def GetItemInfo(self, idx):
898 Collect all relevant data of a listitem, and put it in a list.
902 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
903 l.append(self.GetItemData(idx)) # Itemdata.
904 l.append(self.GetItemText(idx)) # Text first column.
905 for i in range(1, self.GetColumnCount()): # Possible extra columns.
906 l.append(self.GetItem(idx, i).GetText())
907 l.append('catewords')
911 def StartDrag(self, event):
913 Put together a data object for drag-and-drop _from_ this list.
918 while True: # Find all the selected items and put them in a list.
919 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
922 l.append(self.GetItemInfo(idx))
924 # Pickle the items list.
925 itemdata = pickle.dumps(l, 1)
926 # Create our own data format and use it
927 # in a Custom data object.
928 ldata = wx.CustomDataObject("ListCtrlItems")
929 ldata.SetData(itemdata)
930 # Now make a data object for the item list.
931 data = wx.DataObjectComposite()
934 # Create drop source and begin drag-and-drop.
935 dropSource = wx.DropSource(self)
936 dropSource.SetData(data)
937 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
939 print(self.parent.m_listCate.currentItem)
941 # If move, we want to remove the item from this list.
942 #if res == wx.DragMove:
943 # # It's possible we are dragging/dropping from this list to this list.
944 # # In which case, the index we are removing may have changed...
946 # # Find correct position.
947 # l.reverse() # Delete all the items, starting with the last item.
949 # pos = self.FindItem(i[0], i[2])
950 # self.DeleteItem(pos)
953 def Insert(self, x, y, seq):
955 Insert text at given x, y coordinates --- used with drag-and-drop.
958 # Find insertion point.
959 index, flags = self.HitTest((x, y))
961 # if index == wx.NOT_FOUND: # Not clicked on an item.
962 # if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
963 # index = self.GetItemCount() # Append to end of list.
964 # elif self.GetItemCount() > 0:
965 # if y <= self.GetItemRect(0).y: # Clicked just above first item.
966 # index = 0 # Append to top of list.
968 # index = self.GetItemCount() + 1 # Append to end of list.
969 # else: # Clicked on an item.
970 # # Get bounding rectangle for the item the user is dropping over.
971 # rect = self.GetItemRect(index)
973 # # If the user is dropping into the lower half of the rect,
974 # # we want to insert _after_ this item.
975 # # Correct for the fact that there may be a heading involved.
976 # if y > rect.y - self.GetItemRect(0).y + rect.height/2:
978 print('Insert de ListForCateWords', index,flags)
979 if seq[0][-1] == 'words' :
982 categorie = self.parent.m_listCate.getColumnText(self.parent.m_listCate.GetFirstSelected(),0)
983 self.cate.addwordincate(categorie, word, eff)
984 self.dlist = self.cate.getwordstocate()
985 self.RefreshData(self.cate.getcatewords(categorie))
986 self.parent.m_listCate.RefreshData(self.cate.getcate())
987 self.parent.m_listToCate.RefreshData(self.dlist)
988 self.parent.butsave.SetBackgroundColour((255,0,0,255))
991 class MyListDropCate(wx.DropTarget):
993 Drop target for simple lists.
995 def __init__(self, source):
998 source: source listctrl.
1000 wx.DropTarget.__init__(self)
1008 # Specify the type of data we will accept.
1009 self.data = wx.CustomDataObject("ListCtrlItems")
1010 self.SetDataObject(self.data)
1012 #-----------------------------------------------------------------------
1014 # Called when OnDrop returns True.
1015 # We need to get the data and do something with it.
1016 def OnData(self, x, y, d):
1021 # Copy the data from the drag source to our data object.
1023 # Convert it back to a list and give it to the viewer.
1024 ldata = self.data.GetData()
1025 l = pickle.loads(ldata)
1026 self.dv.Insert(x, y, l)
1028 # What is returned signals the source what to do
1029 # with the original data (move, copy, etc.) In this
1030 # case we just return the suggested value given to us.