367e22ad946a4b4c18acb40f380aa6aa6ee00eb1
[iramuteq] / elcategorizator.py
1 # -*- coding: utf-8 -*-
2 #Author: Pierre Ratinaud
3 #Copyright (c) 2022 Pierre Ratinaud
4 #License: GNU/GPL
5
6 import os
7 import wx
8 import wx.xrc
9 from wx.lib.splitter import MultiSplitterWindow
10 from listlex import *
11 import pickle
12 import json
13
14
15
16 class CategoDict :
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]])
21
22     def readjson(self):
23         if self.pathout is not None :
24             with open(self.pathout['cate.json'], 'r', encoding='utf8') as f :
25                 cate = json.load(f)
26         else :
27             cate = {'TOCATE' : {'word1': 3, 'word2' : 2, 'word3' : 5}, 'CATE': {'cat1' : [34,{'word6':30, 'word7':4}], 'cat2' : [20,{'word20':20}]}}
28         return cate
29
30     def save(self) :
31         with open(self.pathout['cate.json'], 'w', encoding='utf8') as f :
32             f.write(json.dumps(self.cate, indent=4))
33         print("json saved!")
34
35     def exportdict(self):
36         pass
37
38     def getcate(self) :
39         cate = []
40         i = 0
41         for val in self.cate['CATE'] :
42             cate.append([i, [val, self.cate['CATE'][val][0]]])
43             i += 1
44         return dict(cate)
45
46     def getwordstocate(self) :
47         words = []
48         i = 0
49         for val in self.cate['TOCATE'] :
50             words.append([i, [val, self.cate['TOCATE'][val]]])
51             i+= 1
52         return dict(words)
53
54     def getcatewords(self, cat) :
55         catewords = []
56         i = 0
57         if cat not in self.cate['CATE'] :
58             return {}
59         for val in self.cate['CATE'][cat][1] :
60             catewords.append([i, [val, self.cate['CATE'][cat][1][val]]])
61             i += 1
62         return dict(catewords)
63
64     def getwordscate(self) :
65         wc = {}
66         for word in self.cate['TOCATE'] :
67             wc[word] = word
68         for categorie in self.cate['CATE'] :
69             for word in self.cate['CATE'][categorie][1] :
70                 wc[word] = categorie
71         return wc
72
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])
77
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])
85
86     def findcatefromword(self, word) :
87         for categorie in self.cate['CATE'] :
88             if word in self.cate['CATE'][categorie][1] :
89                 return categorie
90         return None
91
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])
100
101     def addcatefromwordtocate(self, word, eff) :
102         if word in self.cate['CATE'] :
103             return False
104         else :
105             self.cate['CATE'][word]=[eff,{word:eff}]
106             del(self.cate['TOCATE'][word])
107             return True
108
109     def addcatefromscratch(self) :
110         i = 0
111         while "NewCategory_%i" %i in self.cate['CATE'] :
112             i += 1
113         newcate = "NewCategory_%i" %i
114         self.cate['CATE'][newcate] = [0, {}]
115
116     def addcatefromwordcate(self, word, eff) :
117         if word in self.cate['CATE'] :
118             return False
119         else :
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])
126             return True
127
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])
132
133     def loadcate(self, infile) :
134         if self.cate['CATE'] != {} :
135             print("Categories should be empty")
136             return False
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])
146
147     def makestat(self) :
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
154
155
156 #cate = CategoDict()
157
158
159 #class ElCategorizator ( wx.Panel ):
160 #
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
166 #
167 #        self.cate = CategoDict(self.pathout)
168 #        gsizer =  wx.BoxSizer( wx.VERTICAL )
169 #
170 #        bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
171 #
172 #        self.m_listToCate = ListForWords(self, dlist = self.cate, first = ['eff'])
173 #        bSizer1.Add( self.m_listToCate, 2, wx.ALL|wx.EXPAND, 5 )
174 #
175 #        self.m_listCate = ListForCate(self, dlist = self.cate, first = ['eff'])
176 #        bSizer1.Add( self.m_listCate, 1, wx.ALL|wx.EXPAND, 5 )
177 #
178 #        self.m_listCateWords = ListForCateWords(self, dlist = self.cate, first = ['eff'])
179 #        bSizer1.Add( self.m_listCateWords, 1, wx.ALL|wx.EXPAND, 5 )
180 #
181 #        bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
182 #
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 )
185 #
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 )
188 #
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 )
191 #
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 )
194 #
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 )
197 #
198 #
199 #        bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
200 #
201 #        self.nbword = """Words : {:d} ({:d}) | """
202 #
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 )
214 #
215 #
216 #        gsizer.Add( bSizer2, 0, wx.EXPAND, 5 )
217 #        gsizer.Add( bSizer1, 2, wx.EXPAND, 5 )
218 #        gsizer.Add( bSizer3, 0, wx.EXPAND, 5 )
219 #
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)
226 #        self.OnStat()
227 #        self.SetSizer( gsizer )
228 #        self.Layout()
229 #
230 #    def __del__( self ):
231 #        pass
232 #
233 #
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()
238 #            message.Destroy()
239 #            return
240 #        wildcard = "json|*.json|" \
241 #                   "All file|*.*"
242 #        dlg = wx.FileDialog(
243 #             self, message="Choose a file",
244 #             defaultDir=self.pathout.dirout,
245 #             defaultFile="",
246 #             wildcard=wildcard,
247 #             style=wx.FD_OPEN |
248 #                   wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST |
249 #                   wx.FD_PREVIEW
250 #             )
251 #
252 #        if dlg.ShowModal() == wx.ID_OK:
253 #            paths = dlg.GetPaths()
254 #            path = paths[0]
255 #            self.cate.loadcate(path)
256 #            self.m_listCate.RefreshData(self.cate.getcate())
257 #            self.m_listToCate.RefreshData(self.cate.getwordstocate())
258 #        dlg.Destroy()
259 #
260 #    def OnSave(self, event) :
261 #        self.cate.save()
262 #        self.butsave.SetBackgroundColour((14, 242, 14, 255))
263 #
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):
268 #            newline = []
269 #            for word in line :
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()
276 #        message.Destroy()
277 #
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()
288 #        message.Destroy()
289 #
290 #    def OnStat(self) :
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))
298 #
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):
303 #            newline = []
304 #            for word in line :
305 #                newline.append(wordscate.get(word,word))
306 #            newtab.append(newline)
307 #
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)
315
316
317
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.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 )
328         self.Layout()
329
330
331      def OnStat(self) :
332         self.gparent.OnStat()
333
334 class ElCategorizator ( wx.Panel ):
335
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
339         self.parent = parent
340         self.tableau = tableau
341
342         self.cate = CategoDict(self.pathout)
343         gsizer =  wx.BoxSizer( wx.VERTICAL )
344
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()
352         print(W)
353         W = W - 200
354         if W < 300 :
355             W = 300
356         splitsize = int(W/3)
357
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
367
368
369         bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
370
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 )
373
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 )
376
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 )
379
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 )
382
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 )
385
386
387         bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
388
389         self.nbword = """Words : {:d} ({:d}) | """
390
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
397
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 )
408
409
410         gsizer.Add( bSizer2, 0, wx.EXPAND, 5 )
411         gsizer.Add( splitter, 2, wx.EXPAND, 5 )
412         gsizer.Add( bSizer3, 0, wx.EXPAND, 5 )
413
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)
420         self.OnStat()
421         self.SetSizer( gsizer )
422         self.Layout()
423
424
425
426     def __del__( self ):
427         pass
428
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)
432             message.ShowModal()
433             message.Destroy()
434             return
435         wildcard = "json|*.json|" \
436                    "All file|*.*"
437         dlg = wx.FileDialog(
438              self, message="Choose a file",
439              defaultDir=self.pathout.dirout,
440              defaultFile="",
441              wildcard=wildcard,
442              style=wx.FD_OPEN |
443                    wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST |
444                    wx.FD_PREVIEW
445              )
446
447         if dlg.ShowModal() == wx.ID_OK:
448             paths = dlg.GetPaths()
449             path = paths[0]
450             self.cate.loadcate(path)
451             self.m_listCate.RefreshData(self.cate.getcate())
452             self.m_listToCate.RefreshData(self.cate.getwordstocate())
453         dlg.Destroy()
454
455     def OnSave(self, event) :
456         self.cate.save()
457         self.butsave.SetBackgroundColour((14, 242, 14, 255))
458
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):
463             newline = []
464             for word in line :
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)
470         message.ShowModal()
471         message.Destroy()
472
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)
482         message.ShowModal()
483         message.Destroy()
484
485     def OnStat(self) :
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))
493
494
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):
499             newline = []
500             for word in line :
501                 newline.append(wordscate.get(word,word))
502             newtab.append(newline)
503
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)
511
512
513 class ListForCate(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
514
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)
517         self.parent=parent
518         self.cate = self.parent.cate
519         self.dlist= self.cate.getcate()
520         self.first = first
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)
525             exec(s)
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")
533         self.SetListFont()
534         self.selected = {}
535         i = 0
536         for name in ['Categories'] + self.first :
537             self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
538             i += 1
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)
544
545         #self.SortListItems(1, False)
546         self.SetColumnWidth(0, 300)
547         self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
548
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)
555
556         if self.GetItemCount() != 0 :
557             #self.SetItemState(0, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
558             self.Select(0, on=1)
559
560         dt = MyListDropCate(self)
561         self.SetDropTarget(dt)
562
563     def OnSortColumn(self, evt) :
564         print(self.currentItem)
565         evt.Skip()
566
567     def SetListFont(self) :
568         self.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
569
570     def OnGetItemImage(self, item):
571         return self.p_idx
572
573     def OnBeginEdit(self, event) :
574         self.EditLabel(event.GetIndex())
575         event.Skip()
576
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())
585
586     def ShowWords(self, event) :
587         index = event.GetIndex()
588         try :
589             data = self.cate.getcatewords(self.GetItemText(index))
590             self.parent.m_listCateWords.RefreshData(data)
591             self.parent.m_listCateWords.SetSelection(0)
592         except :
593             pass
594         event.Skip()
595
596     def RefreshData(self, data):
597         try :
598             item = self.currentItem
599         except :
600             item = 0
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)
609         self.parent.OnStat()
610         self.Refresh()
611         try :
612             self.SetSelection(item)
613             self.Focus(item)
614         except :
615             pass
616
617     def GetListCtrl(self):
618         return self
619
620     def GetSortImages(self):
621         return (self.sm_dn, self.sm_up)
622
623     def SortItems(self, sorter=None):
624         try :
625             select = self.currentItem
626             word = self.GetItemData(select)[0]
627         except Exception as e: print('word',e)
628
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
635         try :
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)
639             self.Focus(idx)
640         except Exception as e: print(e)
641
642     def OnGetItemText(self, item, col):
643         index=self.itemIndexMap[item]
644         s = self.itemDataMap[index][col]
645         if isinstance(s, (int, float)):
646             return str(s)
647         else:
648             return s #modification pour python 3
649
650     def OnGetItemAttr(self, item):
651 #        if self.IsSelected(index) == True :
652 #            print('selected', index)
653         index=self.itemIndexMap[item]
654         if item % 2 :
655            return self.attr1
656         else :
657            return self.attr2
658
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))
665         return words
666
667     def GetString(self):
668         return self.getselectedwords()[0]
669
670     def GetSelections(self):
671         return self.getselectedwords()
672
673     def getColumnText(self, index, col):
674         item = self.GetItem(index, col)
675         return item.GetText()
676
677     def GetItemData(self, item) :
678         index=self.itemIndexMap[item]
679         s = self.itemDataMap[index]
680         return s
681
682     def OnItemSelected(self, event):
683         self.currentItem = event.GetIndex() #event.m_itemIndex
684         event.Skip()
685
686     def SetSelection(self, index) :
687         for i in range(0, self.GetItemCount(), 1) :
688             self.Select(i, on=0)
689         self.Select(index, on=1)
690
691     def GetItemInfo(self, idx):
692         """
693         Collect all relevant data of a listitem, and put it in a list.
694         """
695
696         l = []
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())
702         l.append('cate')
703         return l
704
705
706     def StartDrag(self, event):
707         """
708         Put together a data object for drag-and-drop _from_ this list.
709         """
710
711         l = []
712         idx = -1
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)
715             if idx == -1:
716                 break
717             l.append(self.GetItemInfo(idx))
718
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()
727         data.Add(ldata)
728
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)
733
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...
738
739             # Find correct position.
740             l.reverse() # Delete all the items, starting with the last item.
741             for i in l:
742                 pos = self.FindItem(i[0], i[2])
743                 self.DeleteItem(pos)
744
745
746     def Insert(self, x, y, seq):
747         """
748         Insert text at given x, y coordinates --- used with drag-and-drop.
749         """
750
751         # Find insertion point.
752         index, flags = self.HitTest((x, y))
753
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.
760                 else:
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)
765
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:
770             #    index += 1
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 :
775                 for val in seq :
776                     word, eff = val[1]
777                     self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
778             else :
779                 index = self.GetItemCount()
780                 if self.cate.addcatefromwordtocate(word, eff) :
781                     pass
782                 else :
783                     dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
784                     dial.Destroy()
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):
790                 self.Select(i, on=0)
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 :
795                 for val in seq :
796                     word, eff = val[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))
800             else :
801                 index = self.GetItemCount()
802                 if self.cate.addcatefromwordcate(word, eff) :
803                     self.parent.butsave.SetBackgroundColour((255,0,0,255))
804                 else :
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)
813
814
815
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])
822 #                except:
823 #                    pass # Ignore the extra columns.
824 #            index += 1
825
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)
829         self.parent=parent
830         self.cate = self.parent.cate
831         self.dlist= self.cate.getwordstocate()
832         self.first = first
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)
837             exec(s)
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")
845         self.SetListFont()
846         self.selected = {}
847         i = 0
848         for name in ['To categorize'] + self.first :
849             self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
850             i += 1
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)
858
859         self.SortListItems(1, False)
860
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)
864
865         dt = MyListDropCate(self)
866         self.SetDropTarget(dt)
867
868     def OnDClick(self, event) :
869         idx = event.GetIndex()
870         event.Skip()
871
872     def OnItemSelected(self, event):
873         self.currentItem = event.GetIndex() #event.m_itemIndex
874         event.Skip()
875
876     def OnGetItemImage(self, item):
877         return self.i_idx
878
879     def GetItemInfo(self, idx):
880         """
881         Collect all relevant data of a listitem, and put it in a list.
882         """
883
884         l = []
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())
890         l.append('words')
891         return l
892
893
894     def StartDrag(self, event):
895         """
896         Put together a data object for drag-and-drop _from_ this list.
897         """
898
899         l = []
900         idx = -1
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)
903             if idx == -1:
904                 break
905             l.append(self.GetItemInfo(idx))
906
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()
915         data.Add(ldata)
916
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)
921
922
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...
927
928             # Find correct position.
929             l.reverse() # Delete all the items, starting with the last item.
930             for i in l:
931                 pos = self.FindItem(i[0], i[2])
932                 print('detruit : ',pos)
933                 self.DeleteItem(pos)
934
935
936     def Insert(self, x, y, seq):
937         """
938         Insert text at given x, y coordinates --- used with drag-and-drop.
939         """
940
941         # Find insertion point.
942         index, flags = self.HitTest((x, y))
943
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.
950                 else:
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)
955
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:
960                 index += 1
961         word, eff = seq[0][1]
962         if seq[0][-1] == 'catewords' :
963             for val in seq :
964                 word, eff = val[1]
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))
979
980
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)
984         self.parent=parent
985         self.cate = self.parent.cate
986         self.dlist= {}
987         self.first = first
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)
992             exec(s)
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")
1000         self.SetListFont()
1001         self.selected = {}
1002         i = 0
1003         for name in ['Contents'] + self.first :
1004             self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
1005             i += 1
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)
1013
1014         self.SortListItems(1, False)
1015
1016         self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
1017         self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1018
1019         dt = MyListDropCate(self)
1020         self.SetDropTarget(dt)
1021
1022     def OnItemSelected(self, event):
1023         self.currentItem = event.GetIndex() #event.m_itemIndex
1024         event.Skip()
1025
1026
1027     def GetItemInfo(self, idx):
1028         """
1029         Collect all relevant data of a listitem, and put it in a list.
1030         """
1031
1032         l = []
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')
1039         return l
1040
1041
1042     def StartDrag(self, event):
1043         """
1044         Put together a data object for drag-and-drop _from_ this list.
1045         """
1046
1047         l = []
1048         idx = -1
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)
1051             if idx == -1:
1052                 break
1053             l.append(self.GetItemInfo(idx))
1054
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()
1063         data.Add(ldata)
1064
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)
1069         print('current')
1070         print(self.parent.m_listCate.currentItem)
1071
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...
1076
1077         #    # Find correct position.
1078         #    l.reverse() # Delete all the items, starting with the last item.
1079         #    for i in l:
1080         #        pos = self.FindItem(i[0], i[2])
1081         #        self.DeleteItem(pos)
1082
1083
1084     def Insert(self, x, y, seq):
1085         """
1086         Insert text at given x, y coordinates --- used with drag-and-drop.
1087         """
1088         pass
1089         # Find insertion point.
1090         index, flags = self.HitTest((x, y))
1091 #
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.
1098 #                else:
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)
1103 #
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:
1108 #                index += 1
1109         print('Insert de ListForCateWords', index,flags)
1110         if seq[0][-1] == 'words' :
1111             for val in seq :
1112                 word, eff = val[1]
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))
1120
1121
1122 class MyListDropCate(wx.DropTarget):
1123     """
1124     Drop target for simple lists.
1125     """
1126     def __init__(self, source):
1127         """
1128         Arguments:
1129         source: source listctrl.
1130         """
1131         wx.DropTarget.__init__(self)
1132
1133         #------------
1134
1135         self.dv = source
1136
1137         #------------
1138
1139         # Specify the type of data we will accept.
1140         self.data = wx.CustomDataObject("ListCtrlItems")
1141         self.SetDataObject(self.data)
1142
1143     #-----------------------------------------------------------------------
1144
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):
1148         """
1149         ...
1150         """
1151
1152         # Copy the data from the drag source to our data object.
1153         if self.GetData():
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)
1158
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.
1162         return d