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') 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 addcatefromwordcate(self, word, eff) :
110 if word in self.cate['CATE'] :
113 oldcat = self.findcatefromword(word)
114 self.cate['CATE'][word]=[eff,{word:eff}]
115 del(self.cate['CATE'][oldcat][1][word])
116 self.cate['CATE'][oldcat][0] -= eff
117 if self.cate['CATE'][oldcat][0] == 0 :
118 del(self.cate['CATE'][oldcat])
121 def delcate(self, categorie) :
122 for word in self.cate['CATE'][categorie][1] :
123 self.cate['TOCATE'][word] = self.cate['CATE'][categorie][1][word]
124 del(self.cate['CATE'][categorie])
126 def loadcate(self, infile) :
127 if self.cate['CATE'] != {} :
128 print("Categories should be empty")
130 with open(infile, 'r') as f :
131 newcate = json.load(f)
132 for categorie in newcate['CATE'] :
133 self.cate['CATE'][categorie] = [0,{}]
134 for word in newcate['CATE'][categorie][1] :
135 if word in self.cate['TOCATE'] :
136 self.cate['CATE'][categorie][1][word] = self.cate['TOCATE'][word]
137 self.cate['CATE'][categorie][0] += self.cate['TOCATE'][word]
138 del(self.cate['TOCATE'][word])
141 totocat = sum([self.cate['TOCATE'][word] for word in self.cate['TOCATE']])
142 nbtocat = len(self.cate['TOCATE'])
143 nbcate = len(self.cate['CATE'])
144 totcate = sum([self.cate['CATE'][categorie][0] for categorie in self.cate['CATE']])
145 lenwordincate = len([word for categorie in self.cate['CATE'] for word in self.cate['CATE'][categorie][1]])
146 return nbtocat, totocat, nbcate, totcate, lenwordincate
152 class ElCategorizator ( wx.Panel ):
154 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 ):
155 wx.Panel.__init__ ( self, parent, id = id, pos = pos, size = size, style = style, name = name )
156 self.pathout = pathout
158 self.tableau = tableau
160 self.cate = CategoDict(self.pathout)
161 gsizer = wx.BoxSizer( wx.VERTICAL )
163 bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
165 self.m_listToCate = ListForWords(self, dlist = self.cate, first = ['eff'])
166 bSizer1.Add( self.m_listToCate, 2, wx.ALL|wx.EXPAND, 5 )
168 self.m_listCate = ListForCate(self, dlist = self.cate, first = ['eff'])
169 bSizer1.Add( self.m_listCate, 1, wx.ALL|wx.EXPAND, 5 )
171 self.m_listCateWords = ListForCateWords(self, dlist = self.cate, first = ['eff'])
172 bSizer1.Add( self.m_listCateWords, 1, wx.ALL|wx.EXPAND, 5 )
174 bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
176 self.butsave = wx.Button( self, wx.ID_SAVE, u"Save", wx.DefaultPosition, wx.DefaultSize, 0 )
177 bSizer2.Add( self.butsave, 0, wx.ALL, 5 )
179 self.butcsv = wx.Button( self, wx.ID_ANY, u"Export Columns", wx.DefaultPosition, wx.DefaultSize, 0 )
180 bSizer2.Add( self.butcsv, 0, wx.ALL, 5 )
182 self.butdict = wx.Button( self, wx.ID_ANY, u"Export dictonary", wx.DefaultPosition, wx.DefaultSize, 0 )
183 bSizer2.Add( self.butdict, 0, wx.ALL, 5 )
185 self.butload = wx.Button( self, wx.ID_ANY, u"Load a categorization", wx.DefaultPosition, wx.DefaultSize, 0 )
186 bSizer2.Add( self.butload, 0, wx.ALL, 5 )
188 bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
190 self.nbword = """Words : {:d} ({:d}) | """
192 self.stat = """ Words to categorize : {:d} ({}%) - {:d} ({}%) -- Categories : {:d} - {:d} ({}%) - {:d} ({}%)"""
193 # nbtocat, totocat, nbcate, totcate = self.cate.makestat()
194 # lenwords = self.cate.lenwords
195 # totwords = totocat + totcate
196 # prtocat = repr(nbtocat/lenwords)
197 # prtotocat = repr(totocat/totwords)
198 # prcate = repr(totcate/totwords)
199 self.wordtxt = wx.StaticText(self, -1, "")
200 bSizer3.Add( self.wordtxt, 0, wx.ALL, 5 )
201 self.stattxt = wx.StaticText(self, -1, "")
202 bSizer3.Add( self.stattxt, 0, wx.ALL, 5 )
205 gsizer.Add( bSizer2, 0, wx.EXPAND, 5 )
206 gsizer.Add( bSizer1, 2, wx.EXPAND, 5 )
207 gsizer.Add( bSizer3, 0, wx.EXPAND, 5 )
209 self.butsave.Bind(wx.EVT_BUTTON, self.OnSave)
210 self.butcsv.Bind(wx.EVT_BUTTON, self.OnCSV)
211 self.butdict.Bind(wx.EVT_BUTTON, self.OnDict)
212 self.butsave.SetBackgroundColour((14, 242, 14, 255))
213 self.butload.Bind(wx.EVT_BUTTON, self.OnLoad)
215 self.SetSizer( gsizer )
222 def OnLoad(self, event) :
223 if len(self.cate.cate['CATE']) != 0 :
224 print("Categories should be empty")
227 wildcard = "json|*.json|" \
230 self, message="Choose a file",
231 defaultDir=self.pathout.dirout,
235 wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST |
239 if dlg.ShowModal() == wx.ID_OK:
240 paths = dlg.GetPaths()
242 self.cate.loadcate(path)
243 self.m_listCate.RefreshData(self.cate.getcate())
244 self.m_listToCate.RefreshData(self.cate.getwordstocate())
247 def OnSave(self, event) :
249 self.butsave.SetBackgroundColour((14, 242, 14, 255))
251 def OnCSV(self, event) :
252 wordscate = self.cate.getwordscate()
253 newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
254 for line in self.tableau.select_col(self.tableau.selected_col):
257 newline.append(wordscate.get(word,word))
258 newtab.append(newline)
259 with open(self.pathout['tableout.csv'], 'w') as f :
260 f.write('\n'.join(['\t'.join(line) for line in newtab]))
261 print("csv exported !")
263 def OnDict(self, event):
264 with open(self.pathout['dictionnary.txt'], 'w') as f :
265 for categorie in self.cate.cate['CATE'] :
266 f.write(categorie + ': \t' + repr(self.cate.cate['CATE'][categorie][0]) + '\n')
267 for word in self.cate.cate['CATE'][categorie][1] :
268 f.write('\t' + word + ': \t' + repr(self.cate.cate['CATE'][categorie][1][word]) + '\n')
269 for word in self.cate.cate['TOCATE'] :
270 f.write(word + ':\t' + repr(self.cate.cate['TOCATE'][word]) + '\n')
271 print("dictionnary exported !")
274 nbtocat, totocat, nbcate, totcate, lenwordincate = self.cate.makestat()
275 totwords = totocat + totcate
276 prtocat = repr(round((nbtocat/self.cate.lenwords) * 100 ,2))
277 prtotocat = repr(round((totocat/totwords) * 100, 2))
278 prcate = repr(round((totcate/totwords)*100, 2))
279 prwordincate = repr(round((lenwordincate/self.cate.lenwords)*100, 2))
280 self.stattxt.SetLabel(self.stat.format(nbtocat, prtocat, totocat, prtotocat, nbcate, lenwordincate, prwordincate, totcate, prcate))
282 def OnAddToTable(self) :
283 wordscate = self.cate.getwordscate()
284 newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
285 for line in self.tableau.select_col(self.tableau.selected_col):
288 newline.append(wordscate.get(word,word))
289 newtab.append(newline)
293 #class ListPanel(wx.Panel) :
294 # def __init__(self, parent, gparent, List):
295 # wx.Panel.__init__(self, parent, style=wx.BORDER_SUNKEN)
296 # self.parent = parent
297 # self.cate = gparent.cate
298 # self.list = List(self, dlist = gparent.cate, first = ['eff'])
301 #class ElCategorizator ( wx.Panel ):
303 # 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 ):
304 # wx.Panel.__init__ ( self, parent, id = id, pos = pos, size = size, style = style, name = name )
305 # self.pathout = pathout
306 # self.parent = parent
307 # self.tableau = tableau
309 # self.cate = CategoDict(self.pathout)
311 # splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
312 # self.splitter = splitter
313 # sizer = wx.BoxSizer(wx.HORIZONTAL)
314 # sizer.Add(splitter, 1, wx.EXPAND)
315 # self.SetSizer(sizer)
317 # panelwords = ListPanel(splitter, self, ListForWords)
318 # splitter.AppendWindow(panelwords, 150)
319 # panelcate = ListPanel(splitter, self, ListForCate)
320 # splitter.AppendWindow(panelcate, 150)
321 # panelwordscate = ListPanel(splitter, self, ListForCateWords)
322 # splitter.AppendWindow(panelwordscate, 150)
323 # self.m_listToCate = panelwords.list
324 # self.m_listCate = panelcate.list
325 # self.m_listCateWords = panelwordscate.list
327 # def __del__( self ):
330 # def OnSave(self, event) :
332 # self.butsave.SetBackgroundColour((14, 242, 14, 255))
334 # def OnCSV(self, event) :
335 # wordscate = self.cate.getwordscate()
336 # newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
337 # for line in self.tableau.select_col(self.tableau.selected_col):
340 # newline.append(wordscate.get(word,word))
341 # newtab.append(newline)
342 # with open(self.pathout['tableout.csv'], 'w') as f :
343 # f.write('\n'.join(['\t'.join(line) for line in newtab]))
344 # print("csv exported !")
346 # def OnDict(self, event):
347 # with open(self.pathout['dictionnary.txt'], 'w') as f :
348 # for categorie in self.cate.cate['CATE'] :
349 # f.write(categorie + ': \t' + repr(self.cate.cate['CATE'][categorie][0]) + '\n')
350 # for word in self.cate.cate['CATE'][categorie][1] :
351 # f.write('\t' + word + ': \t' + repr(self.cate.cate['CATE'][categorie][1][word]) + '\n')
352 # for word in self.cate.cate['TOCATE'] :
353 # f.write(word + ':\t' + repr(self.cate.cate['TOCATE'][word]) + '\n')
354 # print("dictionnary exported !")
357 class ListForCate(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
359 def __init__(self, parent, dlist = {}, first = [], usefirst = False, menu = True):
360 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)
362 self.cate = self.parent.cate
363 self.dlist= self.cate.getcate()
365 self.il = wx.ImageList(20, 20)
366 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION", "p_idx":"PLUS"}
367 for k,v in list(a.items()):
368 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(20,20)))" % (k,v)
370 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
371 self.attr1 = wx.ListItemAttr()
372 self.attr1.SetBackgroundColour((230, 230, 230))
373 self.attr2 = wx.ListItemAttr()
374 self.attr2.SetBackgroundColour("light blue")
375 #self.attrselected = wx.ListItemAttr()
376 #self.attrselected.SetBackgroundColour("red")
380 for name in ['Categories'] + self.first :
381 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
383 self.itemDataMap = self.dlist
384 self.itemIndexMap = list(self.dlist.keys())
385 self.SetItemCount(len(self.dlist))
386 listmix.ListCtrlAutoWidthMixin.__init__(self)
387 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
389 #self.SortListItems(1, False)
390 self.SetColumnWidth(0, 300)
391 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
393 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
394 self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.ShowWords)
395 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnBeginEdit)
396 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit)
397 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
398 self.Bind(wx.EVT_LIST_COL_CLICK, self.OnSortColumn)
400 if self.GetItemCount() != 0 :
401 #self.SetItemState(0, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
404 dt = MyListDropCate(self)
405 self.SetDropTarget(dt)
407 def OnSortColumn(self, evt) :
408 print(self.currentItem)
411 def SetListFont(self) :
412 self.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
414 def OnGetItemImage(self, item):
417 def OnBeginEdit(self, event) :
418 self.EditLabel(event.GetIndex())
421 def OnEndEdit(self, event) :
422 newlabel = event.GetLabel()
423 idx = event.GetIndex()
424 oldlabel = self.GetItemText(idx)
425 if newlabel not in self.cate.cate['CATE'] :
426 self.cate.cate['CATE'][newlabel] = self.cate.cate['CATE'][oldlabel]
427 del(self.cate.cate['CATE'][oldlabel])
428 self.RefreshData(self.cate.getcate())
430 def ShowWords(self, event) :
431 index = event.GetIndex()
433 data = self.cate.getcatewords(self.GetItemText(index))
434 self.parent.m_listCateWords.RefreshData(data)
435 self.parent.m_listCateWords.SetSelection(0)
440 def RefreshData(self, data):
442 item = self.currentItem
445 self.itemDataMap = data
446 self.itemIndexMap = list(data.keys())
447 self.SetItemCount(len(data))
448 order = self._colSortFlag[self._col]
449 self.SortListItems(self._col, order)
450 #self.SetColumnWidth(0, wx.LIST_AUTOSIZE)
451 #self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
452 #self.SetColumnWidth(0,300)
456 self.SetSelection(item)
461 def GetListCtrl(self):
464 def GetSortImages(self):
465 return (self.sm_dn, self.sm_up)
467 def SortItems(self, sorter=None):
469 select = self.currentItem
470 word = self.GetItemData(select)[0]
471 except Exception as e: print('word',e)
473 listTemp = sorted(self.itemDataMap.items(),
474 key=lambda x:x[1][self._col], reverse= (self._colSortFlag[self._col]!=True))
475 dlist = dict([[line[0],line[1]] for line in listTemp])
476 self.itemDataMap = dlist
477 self.itemIndexMap = list(dlist.keys())
478 self.Refresh() # redraw the list
480 formes = [self.getColumnText(i, 0) for i in range(self.GetItemCount())]
481 idx = [i for i, val in enumerate(formes) if val == word][0]
482 self.SetSelection(idx)
484 except Exception as e: print(e)
486 def OnGetItemText(self, item, col):
487 index=self.itemIndexMap[item]
488 s = self.itemDataMap[index][col]
489 if isinstance(s, (int, float)):
492 return s #modification pour python 3
494 def OnGetItemAttr(self, item):
495 # if self.IsSelected(index) == True :
496 # print('selected', index)
497 index=self.itemIndexMap[item]
503 def getselectedwords(self) :
504 words = [self.getColumnText(self.GetFirstSelected(), 0)]
505 last = self.GetFirstSelected()
506 while self.GetNextSelected(last) != -1:
507 last = self.GetNextSelected(last)
508 words.append(self.getColumnText(last, 0))
512 return self.getselectedwords()[0]
514 def GetSelections(self):
515 return self.getselectedwords()
517 def getColumnText(self, index, col):
518 item = self.GetItem(index, col)
519 return item.GetText()
521 def GetItemData(self, item) :
522 index=self.itemIndexMap[item]
523 s = self.itemDataMap[index]
526 def OnItemSelected(self, event):
527 self.currentItem = event.GetIndex() #event.m_itemIndex
530 def SetSelection(self, index) :
531 for i in range(0, self.GetItemCount(), 1) :
533 self.Select(index, on=1)
535 def GetItemInfo(self, idx):
537 Collect all relevant data of a listitem, and put it in a list.
541 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
542 l.append(self.GetItemData(idx)) # Itemdata.
543 l.append(self.GetItemText(idx)) # Text first column.
544 for i in range(1, self.GetColumnCount()): # Possible extra columns.
545 l.append(self.GetItem(idx, i).GetText())
550 def StartDrag(self, event):
552 Put together a data object for drag-and-drop _from_ this list.
557 while True: # Find all the selected items and put them in a list.
558 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
561 l.append(self.GetItemInfo(idx))
563 # Pickle the items list.
564 itemdata = pickle.dumps(l, 1)
565 # Create our own data format and use it
566 # in a Custom data object.
567 ldata = wx.CustomDataObject("ListCtrlItems")
568 ldata.SetData(itemdata)
569 # Now make a data object for the item list.
570 data = wx.DataObjectComposite()
573 # Create drop source and begin drag-and-drop.
574 dropSource = wx.DropSource(self)
575 dropSource.SetData(data)
576 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
578 # If move, we want to remove the item from this list.
579 if res == wx.DragMove and l[0][-1] != 'cate' :
580 # It's possible we are dragging/dropping from this list to this list.
581 # In which case, the index we are removing may have changed...
583 # Find correct position.
584 l.reverse() # Delete all the items, starting with the last item.
586 pos = self.FindItem(i[0], i[2])
590 def Insert(self, x, y, seq):
592 Insert text at given x, y coordinates --- used with drag-and-drop.
595 # Find insertion point.
596 index, flags = self.HitTest((x, y))
598 if index == wx.NOT_FOUND: # Not clicked on an item.
599 if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
600 index = self.GetItemCount() # Append to end of list.
601 elif self.GetItemCount() > 0:
602 if y <= self.GetItemRect(0).y: # Clicked just above first item.
603 index = -1 # Append to top of list.
605 index = self.GetItemCount() + 1 # Append to end of list.
606 else: # Clicked on an item.
607 # Get bounding rectangle for the item the user is dropping over.
608 rect = self.GetItemRect(index)
610 # If the user is dropping into the lower half of the rect,
611 # we want to insert _after_ this item.
612 # Correct for the fact that there may be a heading involved.
613 #if y > rect.y - self.GetItemRect(0).y + rect.height/2:
615 print('Insert de ListForCate', index, flags)
616 word, eff = seq[0][1]
617 if seq[0][-1] == 'words' :
618 if index < self.GetItemCount() and index != -1 :
621 self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
623 index = self.GetItemCount()
624 if self.cate.addcatefromwordtocate(word, eff) :
627 dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
628 self.dlist = self.cate.getcate()
629 self.RefreshData(self.dlist)
630 self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
631 self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
632 for i in range(0, self.GetItemCount(), 1):
634 self.Select(index, on=1)
635 self.parent.butsave.SetBackgroundColour((255,0,0,255))
636 if seq[0][-1] == 'catewords' :
637 if index < self.GetItemCount() and index != -1 :
640 if word not in self.cate.cate['CATE'][self.GetItemData(index)[0]][1] :
641 self.cate.changewordcate(self.GetItemData(index)[0], word, eff)
642 self.parent.butsave.SetBackgroundColour((255,0,0,255))
644 index = self.GetItemCount()
645 if self.cate.addcatefromwordcate(word, eff) :
646 self.parent.butsave.SetBackgroundColour((255,0,0,255))
648 dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
649 #self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
650 self.dlist = self.cate.getcate()
651 self.RefreshData(self.dlist)
652 self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
653 #self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
654 self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(self.currentItem)[0]))
655 #self.SetSelection(index)
659 # for i in seq: # Insert the item data.
660 # idx = self.InsertItem(index, i[2])
661 # self.SetItemData(idx, i[1])
662 # for j in range(1, self.GetColumnCount()):
663 # try: # Target list can have more columns than source.
664 # self.SetItem(idx, j, i[2+j])
666 # pass # Ignore the extra columns.
669 class ListForWords(ListForCate) :
670 def __init__(self, parent, dlist = {}, first = []):
671 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
673 self.cate = self.parent.cate
674 self.dlist= self.cate.getwordstocate()
676 self.il = wx.ImageList(16, 16)
677 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION"}
678 for k,v in list(a.items()):
679 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
681 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
682 self.attr1 = wx.ListItemAttr()
683 self.attr1.SetBackgroundColour((230, 230, 230))
684 self.attr2 = wx.ListItemAttr()
685 self.attr2.SetBackgroundColour("light blue")
686 #self.attrselected = wx.ListItemAttr()
687 #self.attrselected.SetBackgroundColour("red")
691 for name in ['To categorize'] + self.first :
692 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
694 self.itemDataMap = self.dlist
695 self.itemIndexMap = list(self.dlist.keys())
696 self.SetItemCount(len(self.dlist))
697 listmix.ListCtrlAutoWidthMixin.__init__(self)
698 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
699 self.SetColumnWidth(0, 400)
700 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
702 self.SortListItems(1, False)
704 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
705 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnDClick)
706 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
708 dt = MyListDropCate(self)
709 self.SetDropTarget(dt)
711 def OnDClick(self, event) :
712 idx = event.GetIndex()
715 def OnItemSelected(self, event):
716 self.currentItem = event.GetIndex() #event.m_itemIndex
719 def OnGetItemImage(self, item):
722 def GetItemInfo(self, idx):
724 Collect all relevant data of a listitem, and put it in a list.
728 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
729 l.append(self.GetItemData(idx)) # Itemdata.
730 l.append(self.GetItemText(idx)) # Text first column.
731 for i in range(1, self.GetColumnCount()): # Possible extra columns.
732 l.append(self.GetItem(idx, i).GetText())
737 def StartDrag(self, event):
739 Put together a data object for drag-and-drop _from_ this list.
744 while True: # Find all the selected items and put them in a list.
745 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
748 l.append(self.GetItemInfo(idx))
750 # Pickle the items list.
751 itemdata = pickle.dumps(l, 1)
752 # Create our own data format and use it
753 # in a Custom data object.
754 ldata = wx.CustomDataObject("ListCtrlItems")
755 ldata.SetData(itemdata)
756 # Now make a data object for the item list.
757 data = wx.DataObjectComposite()
760 # Create drop source and begin drag-and-drop.
761 dropSource = wx.DropSource(self)
762 dropSource.SetData(data)
763 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
766 # If move, we want to remove the item from this list.
767 if res == wx.DragMove and l[0][-1] != 'words':
768 # It's possible we are dragging/dropping from this list to this list.
769 # In which case, the index we are removing may have changed...
771 # Find correct position.
772 l.reverse() # Delete all the items, starting with the last item.
774 pos = self.FindItem(i[0], i[2])
775 print('detruit : ',pos)
779 def Insert(self, x, y, seq):
781 Insert text at given x, y coordinates --- used with drag-and-drop.
784 # Find insertion point.
785 index, flags = self.HitTest((x, y))
787 if index == wx.NOT_FOUND: # Not clicked on an item.
788 if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
789 index = self.GetItemCount() # Append to end of list.
790 elif self.GetItemCount() > 0:
791 if y <= self.GetItemRect(0).y: # Clicked just above first item.
792 index = 0 # Append to top of list.
794 index = self.GetItemCount() + 1 # Append to end of list.
795 else: # Clicked on an item.
796 # Get bounding rectangle for the item the user is dropping over.
797 rect = self.GetItemRect(index)
799 # If the user is dropping into the lower half of the rect,
800 # we want to insert _after_ this item.
801 # Correct for the fact that there may be a heading involved.
802 if y > rect.y - self.GetItemRect(0).y + rect.height/2:
804 word, eff = seq[0][1]
805 if seq[0][-1] == 'catewords' :
808 categorie = self.cate.findcatefromword(word)
809 self.cate.addwordinwords(categorie, word, eff)
810 self.RefreshData(self.cate.getwordstocate())
811 self.parent.m_listCate.RefreshData(self.cate.getcate())
812 self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(categorie))
813 self.parent.butsave.SetBackgroundColour((255,0,0,255))
814 elif seq[0][-1] == 'cate' :
815 categorie = seq[0][1][0]
816 self.cate.delcate(categorie)
817 self.RefreshData(self.cate.getwordstocate())
818 self.parent.m_listCate.RefreshData(self.cate.getcate())
819 self.parent.m_listCate.SetSelection(0)
820 self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(self.parent.m_listCate.GetItemText(0)))
821 self.parent.butsave.SetBackgroundColour((255,0,0,255))
824 class ListForCateWords(ListForCate) :
825 def __init__(self, parent, dlist = {}, first = []):
826 wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
828 self.cate = self.parent.cate
831 self.il = wx.ImageList(16, 16)
832 a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","p_idx":"TIP","e_idx":"ERROR","i_idx":"QUESTION"}
833 for k,v in list(a.items()):
834 s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
836 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
837 self.attr1 = wx.ListItemAttr()
838 self.attr1.SetBackgroundColour((230, 230, 230))
839 self.attr2 = wx.ListItemAttr()
840 self.attr2.SetBackgroundColour("light blue")
841 #self.attrselected = wx.ListItemAttr()
842 #self.attrselected.SetBackgroundColour("red")
846 for name in ['Contents'] + self.first :
847 self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
849 self.itemDataMap = self.dlist
850 self.itemIndexMap = list(self.dlist.keys())
851 self.SetItemCount(len(self.dlist))
852 listmix.ListCtrlAutoWidthMixin.__init__(self)
853 listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
854 self.SetColumnWidth(0, 300)
855 self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
857 self.SortListItems(1, False)
859 self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
860 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
862 dt = MyListDropCate(self)
863 self.SetDropTarget(dt)
865 def OnItemSelected(self, event):
866 self.currentItem = event.GetIndex() #event.m_itemIndex
870 def GetItemInfo(self, idx):
872 Collect all relevant data of a listitem, and put it in a list.
876 l.append(idx) # We need the original index, so it is easier to eventualy delete it.
877 l.append(self.GetItemData(idx)) # Itemdata.
878 l.append(self.GetItemText(idx)) # Text first column.
879 for i in range(1, self.GetColumnCount()): # Possible extra columns.
880 l.append(self.GetItem(idx, i).GetText())
881 l.append('catewords')
885 def StartDrag(self, event):
887 Put together a data object for drag-and-drop _from_ this list.
892 while True: # Find all the selected items and put them in a list.
893 idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
896 l.append(self.GetItemInfo(idx))
898 # Pickle the items list.
899 itemdata = pickle.dumps(l, 1)
900 # Create our own data format and use it
901 # in a Custom data object.
902 ldata = wx.CustomDataObject("ListCtrlItems")
903 ldata.SetData(itemdata)
904 # Now make a data object for the item list.
905 data = wx.DataObjectComposite()
908 # Create drop source and begin drag-and-drop.
909 dropSource = wx.DropSource(self)
910 dropSource.SetData(data)
911 res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
913 print(self.parent.m_listCate.currentItem)
915 # If move, we want to remove the item from this list.
916 #if res == wx.DragMove:
917 # # It's possible we are dragging/dropping from this list to this list.
918 # # In which case, the index we are removing may have changed...
920 # # Find correct position.
921 # l.reverse() # Delete all the items, starting with the last item.
923 # pos = self.FindItem(i[0], i[2])
924 # self.DeleteItem(pos)
927 def Insert(self, x, y, seq):
929 Insert text at given x, y coordinates --- used with drag-and-drop.
932 # Find insertion point.
933 index, flags = self.HitTest((x, y))
935 # if index == wx.NOT_FOUND: # Not clicked on an item.
936 # if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
937 # index = self.GetItemCount() # Append to end of list.
938 # elif self.GetItemCount() > 0:
939 # if y <= self.GetItemRect(0).y: # Clicked just above first item.
940 # index = 0 # Append to top of list.
942 # index = self.GetItemCount() + 1 # Append to end of list.
943 # else: # Clicked on an item.
944 # # Get bounding rectangle for the item the user is dropping over.
945 # rect = self.GetItemRect(index)
947 # # If the user is dropping into the lower half of the rect,
948 # # we want to insert _after_ this item.
949 # # Correct for the fact that there may be a heading involved.
950 # if y > rect.y - self.GetItemRect(0).y + rect.height/2:
952 print('Insert de ListForCateWords', index,flags)
953 if seq[0][-1] == 'words' :
956 categorie = self.parent.m_listCate.getColumnText(self.parent.m_listCate.GetFirstSelected(),0)
957 self.cate.addwordincate(categorie, word, eff)
958 self.dlist = self.cate.getwordstocate()
959 self.RefreshData(self.cate.getcatewords(categorie))
960 self.parent.m_listCate.RefreshData(self.cate.getcate())
961 self.parent.m_listToCate.RefreshData(self.dlist)
962 self.parent.butsave.SetBackgroundColour((255,0,0,255))
965 class MyListDropCate(wx.DropTarget):
967 Drop target for simple lists.
969 def __init__(self, source):
972 source: source listctrl.
974 wx.DropTarget.__init__(self)
982 # Specify the type of data we will accept.
983 self.data = wx.CustomDataObject("ListCtrlItems")
984 self.SetDataObject(self.data)
986 #-----------------------------------------------------------------------
988 # Called when OnDrop returns True.
989 # We need to get the data and do something with it.
990 def OnData(self, x, y, d):
995 # Copy the data from the drag source to our data object.
997 # Convert it back to a list and give it to the viewer.
998 ldata = self.data.GetData()
999 l = pickle.loads(ldata)
1000 self.dv.Insert(x, y, l)
1002 # What is returned signals the source what to do
1003 # with the original data (move, copy, etc.) In this
1004 # case we just return the suggested value given to us.