windows
[iramuteq] / iramuteq.py
1 # -*- coding: utf-8 -*-
2 #Author: Pierre Ratinaud
3 #Copyright (c) 2008-2020 Pierre Ratinaud
4 #modification pour python 3 : Laurent Mérat, 6x7 - mai 2020
5 #License: GNU/GPL
6
7 #------------------------------------
8 # import des modules python
9 #------------------------------------
10 import sys
11 import locale
12 import tempfile
13 import codecs
14 import os
15 from random import randint
16 from configparser import ConfigParser, RawConfigParser
17 import webbrowser
18 import logging
19
20 from optparse import OptionParser
21 parser = OptionParser()
22 parser.add_option("-f", "--file", dest="filename",
23                   help="open FILE", metavar="FILE", default=False)
24 (options, args) = parser.parse_args()
25
26 #------------------------------------
27 # import des modules wx
28 #------------------------------------
29 import wx
30 import wx.adv
31 import wx.lib.agw.aui as aui
32 import wx.html
33 import wx.grid
34 import wx.lib.agw.hyperlink as hl
35
36 #------------------------------------
37 # import des fichiers du projet
38 #------------------------------------
39 from analyse_merge import AnalyseMerge
40 from checkinstall import CreateIraDirectory, CheckRPath, FindRPAthWin32, FindRPathNix, CheckRPackages, IsNew, UpgradeConf, CopyConf, RLibsAreInstalled
41 from checkversion import NewVersion
42 from chemins import RscriptsPath, ConstructConfigPath, ConstructDicoPath, ConstructGlobalPath, PathOut
43 from corpus import Builder, SubBuilder, MergeClusters
44 from dialog import PrefDialog
45 from functions import BugReport, PlaySound, History, progressbar
46 from guifunct import *
47 from openanalyse import OpenAnalyse
48 from parse_dmi import ImportDMI
49 from parse_factiva_xml import ImportFactiva
50 from tabafcm import DoAFCM
51 from tabchdalc import AnalyseQuest
52 from tabchddist import ChdCluster
53 from tabchi2 import ChiSquare
54 from tabchi2mcnemar import McNemar
55 from tabfrequence import Frequences, FreqMultiple
56 from tableau import Tableau
57 from tabrsimple import InputText
58 from tabsimi import DoSimi
59 from tabsplitvar import SplitMatrixFromVar
60 from tabverges import Prototypical
61 from textaslexico import Lexico
62 from textlabbe import DistLabbe
63 from textreinert import Reinert
64 from textsimi import SimiTxt, SimiFromCluster
65 from textstat import Stat
66 from textwordcloud import WordCloud, ClusterCloud
67 from tools import Extract
68 from tree import LeftTree
69
70 import langue
71 langue.run()
72
73
74 #------------------------------------
75 # les ID uniques pour tous les éléments qui vont en avoir besoin
76 #------------------------------------
77 ID_OpenData = wx.Window.NewControlId()
78 ID_Import = wx.Window.NewControlId()
79 ID_OpenText = wx.Window.NewControlId()
80 ID_OnOpenAnalyse = wx.Window.NewControlId()
81 ID_Freq = wx.Window.NewControlId()
82 ID_Chi2 = wx.Window.NewControlId()
83 ID_Chi2mc = wx.Window.NewControlId()
84 ID_Student = wx.Window.NewControlId()
85 ID_CHDSIM = wx.Window.NewControlId()
86 ID_CHDReinert = wx.Window.NewControlId()
87 ID_TEXTAFCM = wx.Window.NewControlId()
88 ID_TEXTSTAT = wx.Window.NewControlId()
89 ID_ASLEX = wx.Window.NewControlId()
90 ID_TEXTREINERT = wx.Window.NewControlId()
91 ID_TEXTPAM = wx.Window.NewControlId()
92 ID_CHECKCORPUS = wx.Window.NewControlId()
93 ID_Tabcontent = wx.Window.NewControlId()
94 ID_AFCM = wx.Window.NewControlId()
95 ID_SIMI = wx.Window.NewControlId()
96 ID_CloseTab = wx.Window.NewControlId()
97 ID_SaveTab = wx.Window.NewControlId()
98 ID_CreateText = wx.Window.NewControlId()
99 ID_ACCEUIL = wx.Window.NewControlId()
100 ID_RESULT = wx.Window.NewControlId()
101 ID_HTMLcontent = wx.Window.NewControlId()
102 ID_SimiTxt = wx.Window.NewControlId()
103 ID_proto = wx.Window.NewControlId()
104 ID_ImportTXM = wx.Window.NewControlId()
105 ID_FreqMulti = wx.Window.NewControlId()
106 ID_Splitfromvar = wx.Window.NewControlId()
107 ID_Subtxtfrommeta = wx.Window.NewControlId()
108 ID_Subtxtfromthem = wx.Window.NewControlId()
109 ID_WC = wx.Window.NewControlId()
110 ID_ImportEuro = wx.Window.NewControlId()
111 ID_Fact_xml = wx.Window.NewControlId()
112 ID_Fact_mail = wx.Window.NewControlId()
113 ID_Fact_copy = wx.Window.NewControlId()
114 ID_exportmeta = wx.Window.NewControlId()
115 ID_importdmi = wx.Window.NewControlId()
116 ID_merge = wx.Window.NewControlId()
117 ID_merge_clusters = wx.Window.NewControlId()
118 ID_labbe = wx.Window.NewControlId()
119
120 #------------------------------------
121 # elements de configuration
122 #------------------------------------
123
124 #encodage
125 # if sys.platform == 'darwin' :
126 #    sys.setdefaultencoding('UTF-8')
127 #    wx.SetDefaultPyEncoding('UTF-8')
128 # else :
129 #    sys.setdefaultencoding(locale.getpreferredencoding())
130
131 #chemin de l'application
132 AppliPath = os.path.abspath(os.path.dirname(os.path.realpath(sys.argv[0])))
133
134 #chemin des images
135 ImagePath = os.path.join(AppliPath, 'images')
136
137 #configuration generale
138 DictConfigPath = ConstructGlobalPath(AppliPath)
139 ConfigGlob = ConfigParser()
140 ConfigGlob.read(DictConfigPath['global'])
141 DefaultConf = ConfigParser()
142 DefaultConf.read(DictConfigPath['preferences'])
143
144 #repertoire de l'utilisateur
145 user_home = os.getenv('HOME')
146 if user_home is None :
147     user_home = os.path.expanduser('~')
148
149 UserConfigPath = os.path.abspath(os.path.join(user_home, '.iramuteq-%s' % ConfigGlob.get('DEFAULT', 'version_nb')))
150 ConfigPath = ConstructConfigPath(UserConfigPath)
151
152 #Si pas de fichiers de config utilisateur, on cree le repertoire
153 CreateIraDirectory(UserConfigPath, AppliPath)
154
155 #fichiers log pour windows (py2exe)
156 log = logging.getLogger('iramuteq')
157 fh = logging.FileHandler(os.path.join(UserConfigPath,'stdout.log'))
158 formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
159 fh.setFormatter(formatter)
160 log.addHandler(fh)
161 if sys.platform != 'win32' and sys.platform != 'darwin':
162     ch = logging.StreamHandler()
163     ch.setFormatter(formatter)
164     log.addHandler(ch)
165 log.setLevel(logging.INFO)
166
167
168 class writer(object):
169
170     def write(self, data):
171         if data.strip() != '' :
172             log.info('ERROR : %s' % data)
173
174
175 class printer(object) :
176
177     def write(self, data) :
178         if data.strip() != '' :
179             log.info('Print : %s' % data)
180
181     # pour eviter des lignes de log d'erreur
182     def flush(self):
183         pass
184
185 sys.stderr = writer()
186 sys.stdout = printer()
187
188 images_analyses = {
189         'textroot' : 'textroot.png',
190         'alceste' : 'reinert.png',
191         'reinert' : 'reinert.png',
192         'corpus' : 'textcorpus.png',
193         'wordcloud' :'wordcloud.png',
194         'stat' :'stats.png',
195         'simitxt' : 'simitxt.png',
196         'clustersimitxt' :'clustersimitxt.png',
197         'clustercloud' : 'clustercloud.png',
198         'spec' : 'spec.png',
199         'matroot' : 'matroot.png',
200         'matrix' : 'matrix.png',
201         'freq' : 'frequences.png',
202         'freqmulti' : 'frequences.png',
203         'chi2' : 'chi2.png',
204         'chi2mcnemar' : 'chi2.png',
205         'reinertmatrix' : 'reinertmatrix.png',
206         'simimatrix' : 'simimatrix.png',
207         'simiclustermatrix' : 'simimatrix.png',
208         'proto' : 'proto.png',
209         'TXM' : 'TXM.png',
210         'europress' : 'europress.png',
211         'factiva_xml' : 'factiva_xml.png',
212         'factiva_copy' : 'factiva_copy.png',
213         'factiva_mail': 'factiva_mail.png',
214         'iramuteq' : 'iraicone.png',
215         'subcorpusmeta' : 'subcorpusmeta.png',
216         'subcorpusthema' : 'subcorpusthema.png',
217         'preferences' : 'preferences.png',
218         'exportmetatable' : 'exportmetatable.png',
219         'importdmi' : 'twitter.png',
220         'labbe' : 'spec.png'
221          }
222
223
224 #------------------------------------
225 # l'ensemble du contexte de Iramuteq : menu, fenetre, etc.
226 #------------------------------------
227 class IraFrame(wx.Frame):
228
229     def __init__(self, parent,
230                  id= -1, title="",
231                  pos=wx.DefaultPosition,
232                  size=wx.DefaultSize,
233                  style=wx.DEFAULT_FRAME_STYLE |
234                        wx.SUNKEN_BORDER |
235                        wx.CLIP_CHILDREN):
236         log.info('Starting Iramuteq... ' )
237         log.info('version : %s' % ConfigGlob.get('DEFAULT', 'version'))
238         wx.Frame.__init__(self, parent, id, title, pos, size, style)
239         # configuration
240         self.AppliPath = AppliPath
241         self.images_path = os.path.join(AppliPath,'images')
242         self.UserConfigPath = UserConfigPath
243         #self.RscriptsPath = ConstructRscriptsPath(AppliPath)
244         self.RscriptsPath = PathOut(dirout=os.path.join(AppliPath, 'Rscripts'))
245         self.RscriptsPath.basefiles(RscriptsPath)
246         #self.DictPath = ConstructDicoPath(AppliPath)
247         self.DictPath = ConstructDicoPath(UserConfigPath)
248         self.ConfigGlob = ConfigGlob
249         self.ConfigPath = ConstructConfigPath(self.UserConfigPath)
250         self.pref = RawConfigParser()
251         # workaround for import problem
252         self.SimiFromCluster = SimiFromCluster
253         # tell FrameManager to manage this frame
254         self._mgr = aui.AuiManager()
255         self._mgr.SetManagedWindow(self)
256         self.x = 0
257         #--------------------------------------------------------------------------------
258         # creation menu
259         #--------------------------------------------------------------------------------
260         self.images_analyses = images_analyses
261         for img in images_analyses :
262             self.images_analyses[img] = wx.Image(os.path.join(self.images_path, self.images_analyses[img]),
263                 wx.BITMAP_TYPE_PNG).Scale(16,16).ConvertToBitmap()
264         self.mb = wx.MenuBar()
265
266         # menu 'Fichier' de la barre de menu (en haut de l'écran)
267         file_menu = wx.Menu()
268         item = wx.MenuItem(file_menu, ID_OpenData, _("Open a matrix"), _("Open a matrix"))
269         #item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN))
270         item.SetBitmap(self.images_analyses['matroot'])
271         file_menu.Append(item)
272         item = wx.MenuItem(file_menu, ID_OpenText, _("Open a text corpus"), _("Open a text corpus"))
273         item.SetBitmap(self.images_analyses['textroot'])
274         file_menu.Append(item)
275         item = wx.MenuItem(file_menu, ID_OnOpenAnalyse, _("Open an analysis"), _("Open an analysis"))
276         item.SetBitmap(self.images_analyses['iramuteq'])
277         file_menu.Append(item)
278         item = wx.MenuItem(file_menu, ID_ImportTXM, _("Import from TXM"), _("Import from TXM"))
279         item.SetBitmap(self.images_analyses['TXM'])
280         file_menu.Append(item)
281         item = wx.MenuItem(file_menu, ID_ImportEuro, _("Import from Europress"), _("Import from Europress"))
282         item.SetBitmap(self.images_analyses['europress'])
283         file_menu.Append(item)
284         item = wx.MenuItem(file_menu, ID_importdmi, _("Import from DMI-TCAT (exp.)"), _("Import from DMI-TCAT (exp.)"))
285         item.SetBitmap(self.images_analyses['importdmi'])
286         file_menu.Append(item)
287         item = wx.MenuItem(file_menu, ID_merge, _('Merge graphs'), _('Merge graphs'))
288         file_menu.Append(item)
289         item = wx.MenuItem(file_menu, ID_merge_clusters, _('Corpus from merge clusters'), _('Corpus from merge clusters'))
290         file_menu.Append(item)
291
292         # menu Factiva
293         menuFactiva = wx.Menu()
294         fact_from_xml = wx.MenuItem(menuFactiva, ID_Fact_xml, _("from xml"))
295         fact_from_xml.SetBitmap(self.images_analyses['factiva_xml'])
296         fact_from_mail = wx.MenuItem(menuFactiva, ID_Fact_mail, _("from mail"))
297         fact_from_mail.SetBitmap(self.images_analyses['factiva_mail'])
298         fact_from_txt = wx.MenuItem(menuFactiva, ID_Fact_copy, _("from copy/paste"))
299         fact_from_txt.SetBitmap(self.images_analyses['factiva_copy'])
300         menuFactiva.Append(fact_from_xml)
301         menuFactiva.Append(fact_from_mail)
302         menuFactiva.Append(fact_from_txt)
303         file_menu.Append(-1, _("Import from factiva"), menuFactiva)
304
305         menuTools = wx.Menu()
306         splitvar = wx.MenuItem(menuTools, wx.ID_ANY, _("Split from variable"))
307         extractmod = wx.MenuItem(menuTools, wx.ID_ANY, _("Extract mods"))
308         extractthem = wx.MenuItem(menuTools, wx.ID_ANY, _("Extract thematics"))
309         menuTools.Append(splitvar)
310         menuTools.Append(extractmod)
311         menuTools.Append(extractthem)
312         self.ID_splitvar = splitvar.GetId()
313         self.ID_extractmod = extractmod.GetId()
314         self.ID_extractthem = extractthem.GetId()
315         file_menu.Append(-1, _("Tools"), menuTools)
316
317         # ???
318         #item = wx.MenuItem(file_menu, ID_SaveTab, _(u"Save tab as..."), _(u"Save tab as..."))
319         #item.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE_AS))
320         #file_menu.AppendItem(item)
321
322         file_menu.Append(wx.ID_EXIT, _("Exit"))
323         # sous macOS cet élément est apparemment déplacé automatiquement vers le menu 'pomme' ???
324
325         # menu 'Edition' de la barre de menu (en haut de l'écran)
326         # sous macOS, il est déplacé dans le menu 'App'
327         # alors que le menu édition (copier/coller etc. reste vide)
328         edit_menu = wx.Menu()
329         pref = wx.MenuItem(edit_menu, wx.ID_PREFERENCES, _('Preferences'))
330         pref.SetBitmap(self.images_analyses['preferences'])
331         edit_menu.Append(pref)
332
333         # menu 'Vue' de la barre de menu (en haut de l'écran)
334         view_menu = wx.Menu()
335         home = wx.MenuItem(view_menu, ID_ACCEUIL, _("Home page"))
336         home.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, size = (16,16)))
337         view_menu.Append(home)
338         results = wx.MenuItem(view_menu, ID_RESULT, _('Show results'))
339         results.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, size = (16,16)))
340         view_menu.Append(results)
341
342         # menu 'Analyses de matrice' de la barre de menu (en haut de l'écran)
343         matrix_menu = wx.Menu()
344         matanalyses = [[ID_Freq, _("Frequencies"), 'freq'],
345                        [ID_FreqMulti, _("Multiple  Frequencies"), 'freqmulti'],
346                        [ID_Chi2, _("Chi2"), 'chi2'],
347                        [ID_Chi2mc, _("Chi2 McNemar"), 'chi2mcnemar'],
348                        {'name' : _("Clustering"),
349                         'content' : [[ID_CHDReinert, _("Reinert's Method"), 'reinertmatrix']]
350                        },
351                        [ID_SIMI, _("Similarities Analysis"), 'simimatrix'],
352                        [ID_proto, _("Prototypical Analysis"), 'proto'],
353                        [ID_Splitfromvar, _("Split from variable"), 'subcorpusmeta'],
354                       ]
355         for analyse in matanalyses :
356             if not isinstance(analyse, dict) :
357                 item = wx.MenuItem(matrix_menu, analyse[0], analyse[1])
358                 item.SetBitmap(self.images_analyses.get(analyse[2], wx.Bitmap(16,16)))
359                 matrix_menu.Append(item)
360             else :
361                 nmenu = wx.Menu()
362                 for subana in analyse['content'] :
363                     item = wx.MenuItem(nmenu, subana[0], subana[1])
364                     item.SetBitmap(self.images_analyses.get(subana[2], wx.Bitmap(16,16)))
365                     nmenu.Append(item)
366                 matrix_menu.Append(-1, analyse['name'], nmenu)
367         self.matrix_menu = matrix_menu
368
369         # menu 'Analyse de texte' de la barre de menu (en haut de l'écran)
370         text_menu = wx.Menu()
371         analyses_text = [[ID_TEXTSTAT, _("Statistics"), 'stat'],
372                          [ID_ASLEX, _("Specificities and CA"), 'spec'],
373                          [ID_labbe, _("Labbe Distance"),'labbe'],
374                          {'name' : _("Clustering"),
375                           'content' : [[ID_TEXTREINERT, _("Reinert's Method"), 'alceste']]
376                          },
377                          [ID_SimiTxt, _("Similarities Analysis"), 'simitxt'],
378                          [ID_WC, _("WordCloud"), 'wordcloud'],
379                          {'name' : _("Sub corpus"),
380                           'content' : [[ID_Subtxtfrommeta, _('Sub corpus from metadata'), 'subcorpusmeta'],
381                                        [ID_Subtxtfromthem, _('Sub corpus from thematic'), 'subcorpusthema']]
382                          },
383                          [ID_exportmeta, _("Export metadata table"), 'exportmetatable'],
384                         ]
385         for analyse in analyses_text :
386             if not isinstance(analyse, dict) :
387                 item = wx.MenuItem(text_menu, analyse[0], analyse[1])
388                 item.SetBitmap(self.images_analyses.get(analyse[2], wx.Bitmap(16,16)))
389                 text_menu.Append(item)
390             else :
391                 nmenu = wx.Menu()
392                 for subana in analyse['content'] :
393                     item = wx.MenuItem(nmenu, subana[0], subana[1])
394                     item.SetBitmap(self.images_analyses.get(subana[2], wx.Bitmap(16,16)))
395                     nmenu.Append(item)
396                 text_menu.Append(-1, analyse['name'], nmenu)
397         self.text_menu = text_menu
398
399         # menu 'Aide' et 'A propos' de la barre de menu (en haut de l'écran)
400         # mais le "à propos est déplacé par macOS sous le menu "Pomme"
401         # et il n'a pas d'action apparemment
402         help_menu = wx.Menu()
403         about = wx.MenuItem(help_menu, wx.ID_ABOUT, _("About..."))
404         about.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, size = (16,16)))
405         help_menu.Append(about)
406         help = wx.MenuItem(help_menu, wx.ID_HELP, _("Online help..."))
407         help.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_HELP, size = (16,16)))
408         help_menu.Append(help)
409
410         # après avoir construit chaque menu, on les ajoute à barre de menu (en haut de l'écran)
411         self.mb.Append(file_menu, _("File"))
412         self.mb.Append(edit_menu, _("Edition"))
413         self.mb.Append(view_menu, _("View"))
414         self.mb.Append(matrix_menu, _("Matrix analysis"))
415         self.mb.Append(text_menu, _("Text analysis"))
416         self.mb.Append(help_menu, _("Help"))
417         self.SetMenuBar(self.mb)
418
419         #--------------------------------------------------------------------
420         # barre de statut : sur macOS, c'est la barre en bas de la fenêtre Iramuteq
421         #--------------------------------------------------------------------
422         self.statusbar = self.CreateStatusBar(2, wx.STB_SIZEGRIP)
423         self.statusbar.SetStatusWidths([-2, -3])
424         self.statusbar.SetStatusText(_("Ready"), 0)
425         self.statusbar.SetStatusText(_("Welcome"), 1)
426         # min size for the frame itself isn't completely done.
427         # see the end up FrameManager::Update() for the test
428         # code. For now, just hard code a frame minimum size
429         self.SetMinSize(wx.Size(400, 400))
430
431         #--------------------------------------------------------------------
432         # barre d'outils : le menu de petits icones en haut de la fenetre
433         # il y en a 4 : tb1, tb_text, tb_mat, tb_help
434         #--------------------------------------------------------------------
435         # tb1
436         tb1 = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_FLAT | wx.TB_NODIVIDER)
437         tb1.SetToolBitmapSize(wx.Size(16, 16))
438         tb1.AddTool(ID_OpenData, "OpenData", self.images_analyses['matroot'], shortHelp=_("Open a matrix"))
439         tb1.AddSeparator()
440         tb1.AddTool(ID_OpenText, "OpenText", self.images_analyses['textroot'], shortHelp=_("Open a text corpus"))
441         tb1.AddSeparator()
442         tb1.AddTool(ID_OnOpenAnalyse, "OpenAnalyse", self.images_analyses['iramuteq'], shortHelp= _("Open an analysis"))
443         tb1.AddSeparator()
444         tb1.AddTool(ID_ImportTXM, "ImportTXM", self.images_analyses['TXM'], shortHelp= _("Import from TXM"))
445         tb1.AddSeparator()
446         tb1.AddTool(ID_ImportEuro, "ImportEuro", self.images_analyses['europress'], shortHelp= _("Import from Europress"))
447         tb1.AddSeparator()
448         tb1.AddTool(ID_importdmi, "ImportDMI", self.images_analyses['importdmi'], shortHelp= _("Import from DMI-TCAT (exp.)"))
449         tb1.AddSeparator()
450         tb1.AddTool(ID_Fact_xml, "ImportFactxml", self.images_analyses['factiva_xml'], shortHelp= _("Factiva from xml"))
451         tb1.AddTool(ID_Fact_mail, "ImportFactmail", self.images_analyses['factiva_mail'], shortHelp= _("Factiva from mail"))
452         tb1.AddTool(ID_Fact_copy, "ImportFactcopy", self.images_analyses['factiva_copy'], shortHelp= _("Factiva from copy/paste"))
453         tb1.AddSeparator()
454         tb1.AddTool(wx.ID_PREFERENCES, "Preferences", self.images_analyses['preferences'], shortHelp= _("Preferences"))
455         tb1.AddSeparator()
456         tb1.AddTool(ID_ACCEUIL, "Home", wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, size = (16,16)), shortHelp= _("Home page"))
457         tb1.AddTool(ID_RESULT, "Results", wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, size = (16,16)), shortHelp= _('Show results'))
458         tb1.Realize()
459         # tb_text
460         tb_text = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_FLAT | wx.TB_NODIVIDER)
461         for analyse in analyses_text :
462             if not isinstance(analyse, dict) :
463                 tb_text.AddTool(analyse[0], analyse[1], self.images_analyses.get(analyse[2], wx.Bitmap(16,16)), shortHelp = analyse[1])
464             else :
465                 for subana in analyse['content'] :
466                     tb_text.AddTool(subana[0], subana[1], self.images_analyses.get(subana[2], wx.Bitmap(16,16)), shortHelp = subana[1])
467         tb_text.Realize()
468         # tb_mat
469         tb_mat = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_FLAT | wx.TB_NODIVIDER)
470         for analyse in matanalyses :
471             if not isinstance(analyse, dict) :
472                 tb_mat.AddTool(analyse[0], analyse[1], self.images_analyses.get(analyse[2], wx.Bitmap(16,16)), shortHelp = analyse[1])
473             else :
474                 for subana in analyse['content'] :
475                     tb_mat.AddTool(subana[0], subana[1], self.images_analyses.get(subana[2], wx.Bitmap(16,16)), shortHelp = subana[1])
476         tb_mat.Realize()
477         #tb_help
478         tb_help = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_FLAT | wx.TB_NODIVIDER)
479         tb_help.AddTool(wx.ID_ABOUT, "About", wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, size=(16,16)), shortHelp=_("About..."))
480         tb_help.AddTool(wx.ID_HELP, "Help", wx.ArtProvider.GetBitmap(wx.ART_HELP, size=(16,16)), shortHelp=_("Online help..."))
481         tb_help.Realize()
482
483         # ???
484         self.text_ctrl_txt = wx.TextCtrl(self, -1, "", wx.Point(0, 0), wx.Size(200, 200), wx.NO_BORDER | wx.TE_MULTILINE | wx.TE_RICH2 | wx.TE_READONLY)
485         self._mgr.AddPane(self.text_ctrl_txt, aui.AuiPaneInfo().Name("Text").CenterPane())
486         self._mgr.AddPane(IntroPanel(self), aui.AuiPaneInfo().Name("Intro_Text").CenterPane())
487
488         #------------------------------------------------------------------------------------------------
489         # fichier d'historique de Iramuteq
490         #------------------------------------------------------------------------------------------------
491         #if not os.path.exists(os.path.join(UserConfigPath, 'history.db')) :
492         #    with open(os.path.join(UserConfigPath, 'history.db'), 'w') as f :
493         #        f.write('')
494         self.history = History(os.path.join(UserConfigPath, 'historyIramuteq'))
495         # l'extension ".db" est ajoutée automatiquement par le module
496
497         #------------------------------------------------------------------------------------------------
498         # colonne gauche de la fenetre de Iramuteq, classe "Lefttree"
499         #------------------------------------------------------------------------------------------------
500         #self.history.dostat()
501         self.tree = LeftTree(self)
502         self._mgr.AddPane(self.tree,
503             aui.AuiPaneInfo().
504             Name("lefttree").
505             Caption(_("Historic")).
506             Left().
507             MinSize(wx.Size(200,500)).
508             Layer(1).
509             Position(1).
510             CloseButton(False).
511             MaximizeButton(True).
512             MinimizeButton(True))
513
514         self.nb = aui.AuiNotebook(self,
515             -1,
516             wx.DefaultPosition,
517             wx.DefaultSize,
518             aui.AUI_NB_DEFAULT_STYLE)
519             # | aui.AUI_NB_TAB_EXTERNAL_MOVE | aui.AUI_NB_TAB_MOVE | aui.AUI_NB_TAB_FLOAT | wx.NO_BORDER)
520         notebook_flags = aui.AUI_NB_DEFAULT_STYLE
521         # | aui.AUI_NB_TAB_EXTERNAL_MOVE | aui.AUI_NB_TAB_MOVE | aui.AUI_NB_TAB_FLOAT| wx.NO_BORDER
522         self.nb.SetAGWWindowStyleFlag(notebook_flags)
523         self.nb.SetArtProvider(aui.ChromeTabArt())
524         #self.nb.SetArtProvider(aui.VC8TabArt())
525         #self.nb.parent = self
526         #self._notebook_style = aui.AUI_NB_DEFAULT_STYLE | aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER
527
528         #------------------------------------------------------------------------------------------------
529         # colonne droite de la fenetre de Iramuteq "Tab_content"
530         #------------------------------------------------------------------------------------------------
531         self._mgr.AddPane(self.nb,
532             aui.AuiPaneInfo().
533             Name("Tab_content").
534             CenterPane())
535         #self._mgr.AddPane(self.Sheet, wx.aui.AuiPaneInfo().Name("Data").CenterPane())
536         #self._mgr.AddPane(self.Sheet, aui.AuiPaneInfo().Name("Data").CenterPane())
537         self.nb.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnCloseTab)
538         self.nb.Bind(aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
539
540         #------------------------------------------------------------------------------------------------
541         # ajout des toolbars à la fenetre de Iramuteq
542         # Iramuteq n'utilise pas directement les 'toolbar' au sens de wx.python
543         # mais en fait des ToolbarPane ???
544         #------------------------------------------------------------------------------------------------
545         self._mgr.AddPane(tb1, aui.AuiPaneInfo().
546             Name("tb1").
547             Caption("Fichiers").
548             ToolbarPane().
549             Top().
550             LeftDockable(True).
551             RightDockable(False))
552         self._mgr.AddPane(tb_text, aui.AuiPaneInfo().
553             Name("tb_text").
554             Caption("analyse_text").
555             ToolbarPane().
556             Top().
557             LeftDockable(True).
558             RightDockable(False))
559         self._mgr.AddPane(tb_mat, aui.AuiPaneInfo().
560             Name("tb_mat").
561             Caption("analyse_matrix").
562             ToolbarPane().
563             Top().
564             LeftDockable(True).
565             RightDockable(False))
566         self._mgr.AddPane(tb_help, aui.AuiPaneInfo().
567             Name("tb_help").
568             Caption("help").
569             ToolbarPane().
570             Top().
571             LeftDockable(True).
572             RightDockable(False))
573 # ces deux toolbars sont cachées car elles dépendent du contexte des éléments sélectionnés dans lefttree
574         self._mgr.GetPane('tb_text').Hide()
575         self._mgr.GetPane('tb_mat').Hide()
576
577         self.ShowAPane("Intro_Text")
578         self._mgr.GetPane("lefttree").Show()
579         self._mgr.GetPane("classif_tb").Hide() # utilisé nulle part ailleurs que sur cette ligne ???
580         # "commit" all changes made to FrameManager
581         self._mgr.Update()
582
583         # Attache les événements aux éléments d'interface
584         self.Bind(wx.EVT_MENU, self.OnAcceuil, id=ID_ACCEUIL)
585         self.Bind(wx.EVT_MENU, self.ShowTab, id=ID_RESULT)
586         self.Bind(wx.EVT_MENU, self.OnOpenData, id=ID_OpenData)
587         self.Bind(wx.EVT_MENU, self.OnOpenText, id=ID_OpenText)
588         self.Bind(wx.EVT_MENU, self.OnOpenAnalyse, id=ID_OnOpenAnalyse)
589         self.Bind(wx.EVT_MENU, self.import_factiva_xml, fact_from_xml)
590         self.Bind(wx.EVT_MENU, self.import_factiva_mail, fact_from_mail)
591         self.Bind(wx.EVT_MENU, self.import_factiva_txt, fact_from_txt)
592         self.Bind(wx.EVT_MENU, self.ExtractTools, splitvar)
593         self.Bind(wx.EVT_MENU, self.ExtractTools, extractmod)
594         self.Bind(wx.EVT_MENU, self.ExtractTools, extractthem)
595         self.Bind(wx.EVT_MENU, self.OnFreq, id=ID_Freq)
596         self.Bind(wx.EVT_MENU, self.OnFreqMulti, id=ID_FreqMulti)
597         self.Bind(wx.EVT_MENU, self.OnChi2, id=ID_Chi2)
598         self.Bind(wx.EVT_MENU, self.OnChi2McNemar, id=ID_Chi2mc)
599         self.Bind(wx.EVT_MENU, self.OnStudent, id=ID_Student)
600         self.Bind(wx.EVT_MENU, self.OnCHDSIM, id=ID_CHDSIM)
601         self.Bind(wx.EVT_MENU, self.OnCHDReinert, id=ID_CHDReinert)
602         self.Bind(wx.EVT_MENU, self.OnAFCM, id=ID_AFCM)
603         self.Bind(wx.EVT_MENU, self.OnProto, id=ID_proto)
604         self.Bind(wx.EVT_MENU, self.OnSplitVar, id = ID_Splitfromvar)
605         #self.Bind(wx.EVT_MENU, self.OnRCode, id=ID_RCODE) #???
606         #self.Bind(wx.EVT_MENU, self.OnSplitVar, id=ID_SPLITVAR) #???
607         #self.Bind(wx.EVT_MENU, self.OnCheckcorpus, id = ID_CHECKCORPUS) #???
608         self.Bind(wx.EVT_MENU, self.OnTextStat, id=ID_TEXTSTAT)
609         self.Bind(wx.EVT_MENU, self.OnTextSpec, id=ID_ASLEX)
610         self.Bind(wx.EVT_MENU, self.OnTextLabbe, id=ID_labbe)
611         self.Bind(wx.EVT_MENU, self.OnTextAfcm, id=ID_TEXTAFCM)
612         self.Bind(wx.EVT_MENU, self.OnTextReinert, id=ID_TEXTREINERT)
613         self.Bind(wx.EVT_MENU, self.OnPamSimple, id=ID_TEXTPAM)
614         self.Bind(wx.EVT_MENU, self.OnSimiTxt, id=ID_SimiTxt)
615         self.Bind(wx.EVT_MENU, self.OnWordCloud, id=ID_WC)
616         self.Bind(wx.EVT_MENU, self.OnSubText, id = ID_Subtxtfrommeta)
617         self.Bind(wx.EVT_MENU, self.OnSubText, id = ID_Subtxtfromthem)
618         self.Bind(wx.EVT_MENU, self.OnSimiTab, id=ID_SIMI)
619         self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)
620         #self.Bind(wx.EVT_MENU, self.OnSaveTabAs, id=ID_SaveTab) #???
621         self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
622         self.Bind(wx.EVT_MENU, self.OnHelp, id=wx.ID_HELP)
623         self.Bind(wx.EVT_MENU, self.OnPref, id=wx.ID_PREFERENCES)
624         self.Bind(wx.EVT_MENU, self.OnImportTXM, id=ID_ImportTXM)
625         self.Bind(wx.EVT_MENU, self.OnImportEuropress, id=ID_ImportEuro)
626         self.Bind(wx.EVT_MENU, self.OnImportDMI, id=ID_importdmi)
627         self.Bind(wx.EVT_MENU, self.OnExportMeta, id=ID_exportmeta)
628         self.Bind(wx.EVT_MENU, self.OnMergeGraph, id = ID_merge)
629         self.Bind(wx.EVT_MENU, self.OnMergeClusters, id = ID_merge_clusters)
630         self.Bind(wx.EVT_CLOSE, self.OnClose)
631
632         flags = self._mgr.GetAGWFlags()
633         #flags &= ~wx.aui.AUI_MGR_TRANSPARENT_HINT
634         #flags &= ~wx.aui.AUI_MGR_VENETIAN_BLINDS_HINT
635         #flags &= ~wx.aui.AUI_MGR_RECTANGLE_HINT
636         flags &= ~(aui.AUI_MGR_RECTANGLE_HINT | aui.AUI_MGR_ALLOW_FLOATING)
637         self._mgr.SetAGWFlags(self._mgr.GetAGWFlags() ^ (aui.AUI_MGR_RECTANGLE_HINT | aui.AUI_MGR_ALLOW_FLOATING))
638         self._mgr.GetArtProvider().SetMetric(aui.AUI_DOCKART_GRADIENT_TYPE, aui.AUI_GRADIENT_HORIZONTAL)
639         self.GetDockArt().SetColor(aui.AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR, "#00FFF9")
640         self.DoUpdate()
641         self._icon = wx.Icon(os.path.join(ImagePath, "iraicone.ico"), wx.BITMAP_TYPE_ICO)
642         self.SetIcon(self._icon)
643
644         self.ctrl = ""
645         self.input_path = [False]
646         self.TEMPDIR = tempfile.mkdtemp('iramuteq')
647         self.FileTabList = []
648         self.listbar=[]
649         self.DictTab = {}
650         self.FreqNum = 0
651         self.colsep = ''
652         self.txtsep = ''
653         self.g_header = False
654         self.g_id = False
655         self.table = ''
656         self.fileforR = ''
657         self.filename = ''
658         self.nastrings = ''
659         self.encode = ''
660         self.SysEncoding = sys.getdefaultencoding()
661         self.syscoding = sys.getdefaultencoding()
662         if self.SysEncoding == 'mac-roman' : self.SysEncoding = 'MacRoman'
663         self.type = ''
664         #------------------------------------------------------------------------------------------------
665         # P3
666         # 'view', 'matrix' et 'text' sont des valeurs attendues par la fonction ShowMenu
667         #self.ShowMenu('view', True)
668         #self.ShowMenu('matrix', False)
669         #self.ShowMenu('text', False)
670         # je commente ces trois lignes car je ne comprends pas
671         # mais je les garde pour le moment, au cas où il y a un mécanisme que je n'ai pas encore compris
672         #------------------------------------------------------------------------------------------------
673         self._mgr.Update()
674         self.DataPop = False
675         self.DataTxt = False
676         self.Text = ''
677         self.lexique = None
678         self.corpus = None
679
680     def finish_init(self) :
681         try :
682             self.pref.read(self.ConfigPath['preferences'])
683             if IsNew(self) :
684                 UpgradeConf(self)
685                 self.pref.read(self.ConfigPath['preferences'])
686                 New = True
687             else :
688                 CopyConf(self)
689                 New = False
690         except :
691             UpgradeConf(self)
692             self.pref.read(self.ConfigPath['preferences'])
693             New = True
694         self.sound = self.pref.getboolean('iramuteq', 'sound')
695         self.check_update = self.pref.getboolean('iramuteq', 'checkupdate')
696         self.version = ConfigGlob.get('DEFAULT', 'version')
697         # configuration des chemins de R
698         self.PathPath = ConfigParser()
699         self.PathPath.read(ConfigPath['path'])
700         BestRPath = False
701         if not CheckRPath(self.PathPath) :
702             if sys.platform == 'win32':
703                 BestRPath = FindRPAthWin32()
704             else:
705                 BestRPath = FindRPathNix()
706             if BestRPath:
707                 self.PathPath.set('PATHS', 'rpath', BestRPath)
708                 with open(ConfigPath['path'], 'w') as f :
709                     self.PathPath.write(f)
710         else:
711             BestRPath = True
712         if BestRPath :
713             self.RPath = self.PathPath.get('PATHS', 'rpath')
714             if New :
715                 CheckRPackages(self)
716             if not RLibsAreInstalled(self) :
717                 CheckRPackages(self)
718         else :
719             msg = '\n'.join([_("Can't find R executable"), _("If R is not installed, get it from http://www.r-project.org."),
720                              _("If R is installed, report its path in Preferences."),
721                              _("IRaMuTeQ does not work without R.")])
722             dlg = wx.MessageDialog(self, msg, _("Problem"), wx.OK | wx.ICON_WARNING)
723             dlg.CenterOnParent()
724             if dlg.ShowModal() in [wx.ID_NO, wx.ID_CANCEL]:
725                 pass
726             dlg.Destroy()
727
728     def OnVerif(self, evt) :
729         pack = CheckRPackages(self)
730         if pack :
731             dlg = wx.MessageDialog(self, _("Installation OK"), _("Installation"), wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP)
732             dlg.CenterOnParent()
733             if dlg.ShowModal() in [wx.ID_NO, wx.ID_CANCEL]:
734                 evt.Veto()
735
736     # appelé par des fonctions de ce fichier et tree.py : OnSelChanged
737     # vu comme elle est écrite, impossible de gérer
738     # l'affichage/masquage des toolbars en fonction du contexte
739     def ShowMenu(self, menu, Show=True):
740         if menu == 'text' :
741             menu_pos = 4
742             if Show :
743                 self._mgr.GetPane('tb_text').Show()
744             else :
745                 self._mgr.GetPane('tb_text').Hide()
746         elif menu == 'matrix' :
747             menu_pos = 3
748             if Show :
749                 self._mgr.GetPane('tb_mat').Show()
750             else :
751                 self._mgr.GetPane('tb_mat').Hide()
752         elif menu == 'view' :
753             menu_pos = 2
754         else :
755             menu_pos = None
756         if not menu_pos is None :
757             self.mb.EnableTop(menu_pos, Show)
758             self.mb.Refresh()
759         self._mgr.Update()
760
761     #--------------------------------------------------------------------
762     # fin de __init__ du wx.Frame
763     #--------------------------------------------------------------------
764
765     # evenement attaché au bouton de fermeture des fenetres ou onglets ?
766     def OnClose(self, event):
767         print('onclose Iramuteq')
768         with open(self.ConfigPath['path'], 'w') as f :
769             self.PathPath.write(f)
770         self._mgr.UnInit()
771         del self._mgr
772         self.Destroy()
773
774     # evenement attaché au menu 'ouvrir matrice'
775     def OnOpenData(self, event):
776         print('on open data')
777         inputname, self.input_path = OnOpen(self, "Data")
778         if inputname:
779             # filename = self.input_path[0]
780             self.tableau = Tableau(self,os.path.abspath(self.input_path[0]))
781             val = get_table_param(self, self.input_path[0])
782             if val == wx.ID_OK :
783                 busy = wx.BusyInfo(_("Please wait..."), self)
784                 wx.SafeYield()
785                 try :
786                     self.tableau.make_content()
787                     OpenAnalyse(self, self.tableau.parametres)
788                     self.tree.OnItemAppend(self.tableau.parametres)
789                     del busy
790                 except :
791                     del busy
792                     BugReport(self)
793                 # self.tableau.show_tab()
794
795     # evenement attaché au menu 'ouvrir analyse'
796     def OnOpenAnalyse(self, event):
797         print('on open analyse')
798         self.AnalysePath = OnOpen(self, "Analyse")
799         if self.AnalysePath :
800             OpenAnalyse(self, self.AnalysePath[1][0], True)
801             self.ShowMenu('view')
802
803     # evenement attaché au menu 'ouvrir un texte/corpus'
804     def OnOpenText(self, event):
805         print('on open text')
806         inputname, self.input_path = OnOpen(self, "Texte")
807         self.filename = self.input_path[0]
808         if inputname:
809             self.OpenText()
810
811     # evenement attaché au menu 'ouvrir analyse'
812     def OnSubText(self, evt, corpus = None, parametres = None):
813         print('on sub text')
814         if corpus is None :
815             corpus = self.tree.getcorpus()
816         if evt.GetId() == ID_Subtxtfrommeta :
817             parametres = {'frommeta' : True}
818         elif evt.GetId() == ID_Subtxtfromthem :
819             parametres = {'fromtheme' : True}
820         builder = SubBuilder(self, corpus, parametres)
821         if builder.res == wx.ID_OK :
822             busy = wx.BusyInfo(_("Please wait..."), self)
823             wx.SafeYield()
824             corpus = builder.doanalyse()
825             self.history.add(corpus.parametres)
826             OpenAnalyse(self, corpus.parametres)
827             self.tree.OnItemAppend(corpus.parametres)
828             del busy
829
830     # action d'ouverture d'un texte
831     def OpenText(self):
832         print('open text')
833         builder =  Builder(self, 5)
834         if builder.res == wx.ID_OK :
835             try :
836                 corpus = builder.doanalyse()
837                 self.history.add(corpus.parametres)
838                 self.tree.OnItemAppend(corpus.parametres)
839                 OpenAnalyse(self, corpus.parametres)
840             except :
841                 builder.dlg.Destroy()
842                 BugReport(self)
843             else :
844                 count = 1
845                 keepGoing = builder.dlg.Update(count, "Lecture du fichier")
846                 self.ShowMenu('view')
847                 self.ShowMenu('text')
848                 self.ShowMenu('matrix', False)
849                 self.type = "Texte"
850                 self.DataTxt = False
851                 self.Text = ''
852                 count += 1
853                 keepGoing = builder.dlg.Update(count, "Chargement du dictionnaire")
854                 builder.dlg.Destroy()
855
856     # evenement attaché au menu 'quitter'
857     def OnExit(self, event):
858         self.Close()
859
860     # evenement attaché au menu 'à propos'
861     def OnAbout(self, event):
862         print('on about')
863         info = wx.adv.AboutDialogInfo()
864         info.Name = ConfigGlob.get('DEFAULT', 'name')
865         info.Version = ConfigGlob.get('DEFAULT', 'version')
866         info.Copyright = ConfigGlob.get('DEFAULT', 'copyright')
867         info.Translators = ConfigGlob.get('DEFAULT', 'translators').split(';')
868         info.Description = """
869 Interface de R pour les Analyses Multidimensionnelles
870 de Textes et de Questionnaires
871
872 Un logiciel libre
873 construit avec des logiciels libres.
874
875 Laboratoire LERASS
876
877 REPERE
878 """
879         info.WebSite = ("http://www.iramuteq.org", "Site web IRaMuTeQ")
880         dev = ConfigGlob.get('DEFAULT', 'dev').split(';')
881         info.Developers = dev
882         info.License = """Iramuteq est un logiciel libre ; vous pouvez le diffuser et/ou le modifier
883 suivant les termes de la Licence Publique Générale GNU telle que publiée 
884 par la Free Software Foundation ; soit la version 2 de cette licence, 
885 soit (à votre convenance) une version ultérieure.
886
887 Iramuteq est diffusé dans l'espoir qu'il sera utile, 
888 mais SANS AUCUNE GARANTIE ; sans même une garantie implicite 
889 de COMMERCIALISATION ou d'ADÉQUATION À UN USAGE PARTICULIER. 
890 Voyez la Licence Publique Générale GNU pour plus de détails.
891
892 Vous devriez avoir reçu une copie de la Licence Publique Générale GNU
893 avec Iramuteq ; sinon, veuillez écrire à la Free Software Foundation,
894 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, États-Unis."""
895         wx.adv.AboutBox(info)
896
897     # appelé seulement pour l'initialisation de la fenetre principale de Iramuteq
898     def GetDockArt(self):
899         return self._mgr.GetArtProvider()
900
901     # appelé seulement pour l'initialisation de la fenetre principale de Iramuteq
902     def DoUpdate(self):
903         self._mgr.Update()
904
905     # action ou évènement ?
906     def OnPageChanged(self, event) :
907         new = event.GetSelection()
908         nobject = event.GetEventObject()
909         parent = nobject.GetParent()
910         if isinstance(parent, IraFrame) :
911             npage = self.nb.GetPage(new)
912             if 'parametres' in dir(npage) :
913                 self.tree.GiveFocus(uuid=npage.parametres['uuid'])
914                 if npage.parametres.get('matrix', False) :
915                     self.ShowMenu('text', False)
916                     self.ShowMenu('matrix', True)
917                 elif npage.parametres.get('corpus', False) :
918                     self.ShowMenu('text')
919                     self.ShowMenu('matrix', False)
920
921     # action ou évènement ?
922     def OnCloseTab(self, evt):
923         #log.info('Closing tab %s' % str(evt.GetEventObject()))
924         ctrl = evt.GetEventObject()
925         if isinstance(ctrl.GetParent(), aui.AuiNotebook) or isinstance(ctrl.GetParent(), wx.Panel):
926             notebook = True
927         else :
928             notebook = False
929         page = self.nb.GetPage(self.nb.GetSelection())
930         if 'parametres' in dir(page) and isinstance(ctrl.GetParent(), IraFrame) :
931             self.history.rmtab(page.parametres)
932             self.tree.CloseItem(uuid = page.parametres['uuid'])
933         TabTitle = self.nb.GetPageText(self.nb.GetSelection())
934         if self.nb.GetPageCount() == 1 and not notebook :
935             self.LastTabClose()
936
937     # action ou évènement ?
938     def LastTabClose(self) :
939         if self.nb.GetPageCount() == 1 :
940             if self.DataTxt :
941                 self.ShowAPane("Text")
942             elif self.DataPop :
943                 self.ShowAPane("Data")
944             else :
945                 self.ShowAPane("Intro_Text")
946
947     # action ou évènement ?
948     def GetStartPosition(self):
949         self.x = self.x + 20
950         x = self.x
951         pt = self.ClientToScreen(wx.Point(0, 0))
952         return wx.Point(pt.x + x, pt.y + x)
953
954     # action ou évènement ?
955     def ShowAPane(self, panel):
956         for pane in self._mgr.GetAllPanes() :
957             if not pane.IsToolbar() and pane.name != 'lefttree':
958                 pane.Hide()
959         self._mgr.GetPane(panel).Show()
960         self._mgr.Update()
961
962     # action ou évènement ?
963     def OnAcceuil(self, event):
964         self.ShowAPane("Intro_Text")
965         event.Skip()
966
967     # action ou évènement ?
968     def CreateHTMLCtrl(self):
969         ctrl = wx.html.HtmlWindow(self, -1, wx.DefaultPosition, wx.Size(400, 300))
970         if "gtk2" in wx.PlatformInfo:
971             ctrl.SetStandardFonts()
972         ctrl.SetPage("text")
973         return ctrl
974
975     # action ou évènement ?
976     def ShowTab(self, evt):
977         self.ShowAPane("Tab_content")
978
979     ################################################################
980     #debut des analyses
981     ################################################################
982     def analyse_matrix(self, analyse, analyse_type = '', matrix = None, parametres = None, dlgnb = 1):
983         if matrix is None :
984             matrix = self.tree.getmatrix()
985         if parametres is not None :
986             parametres['type'] = analyse_type
987         else :
988             parametres = {'type' : analyse_type}
989         try :
990             #print 'plus de bug@@@@@@@@@@@@@@@@@@@@@@'
991             analyse(self, matrix, parametres = parametres, dlg = dlgnb)
992         except:
993             BugReport(self)
994
995     def OnFreq(self, event, matrix = None):
996         self.analyse_matrix(Frequences, analyse_type = 'freq', matrix = matrix, dlgnb = 3)
997
998     def OnFreqMulti(self, event, matrix = None):
999         self.analyse_matrix(FreqMultiple, analyse_type = 'freqmulti', matrix = matrix, dlgnb = 3)
1000
1001     def OnChi2(self, event, matrix = None):
1002         self.analyse_matrix(ChiSquare, matrix = matrix, analyse_type = 'chi2', dlgnb = 3)
1003
1004     def OnChi2McNemar(self, event, matrix = None):
1005         self.analyse_matrix(McNemar, matrix = matrix, analyse_type = 'chi2mcnemar', dlgnb = 3)
1006
1007     def OnSimiTab(self, event, matrix = None):
1008         self.analyse_matrix(DoSimi, matrix = matrix, analyse_type = 'simimatrix', dlgnb = 5)
1009
1010     def OnCHDReinert(self, event, matrix = None):
1011         #if matrix is None :
1012         #    matrix = self.tree.getmatrix()
1013         #AnalyseQuest(self, matrix, parametres = {'type' : 'reinertmatrix'}, dlg = 3)
1014         self.analyse_matrix(AnalyseQuest, matrix = matrix, analyse_type = 'reinertmatrix', dlgnb = 5)
1015
1016     def OnStudent(self, event):
1017         try:
1018             MakeStudent(self)
1019         except:
1020             BugReport(self)
1021
1022     def OnRCode(self, event):
1023         try:
1024             InputText(self)
1025         except:
1026             BugReport(self)
1027
1028     def OnCHDSIM(self, event):
1029         try:
1030             chdsim = ChdCluster(self)
1031             if chdsim.val == wx.ID_OK:
1032                 PlaySound(self)
1033         except:
1034             BugReport(self)
1035
1036 #     def OnCHDReinert(self, event):
1037 #         try:
1038 #          #   print('PLUS DE BUG SUR ALCESTE QUESTIONNAIRE')
1039 #             self.quest = AnalyseQuest(self)
1040 #             if self.quest.val == wx.ID_OK:
1041 #                 PlaySound(self)
1042 #         except:
1043 #             BugReport(self)
1044
1045     def OnMergeGraph(self, evt):
1046         #FIXME
1047         AnalyseMerge(self, {'type': 'merge', 'fileout' : '/tmp/test.txt'}, dlg = 5)
1048
1049     def OnMergeClusters(self, evt) :
1050         print('on merge clusters')
1051         builder = MergeClusters(self, {})
1052         if builder.res == wx.ID_OK :
1053             busy = wx.BusyInfo(_("Please wait..."), self)
1054             wx.SafeYield()
1055             corpus = builder.doanalyse()
1056             self.history.add(corpus.parametres)
1057             OpenAnalyse(self, corpus.parametres)
1058             self.tree.OnItemAppend(corpus.parametres)
1059             del busy
1060
1061     def OnProto(self, evt, matrix = None) :
1062         self.analyse_matrix(Prototypical, matrix = matrix, analyse_type = 'proto', dlgnb = 3) 
1063         #Prototypical(self, {'type' : 'proto'})
1064
1065     def OnSplitVar(self, evt, matrix = None):
1066         if matrix is None :
1067             matrix = self.tree.getmatrix()
1068         self.analyse_matrix(SplitMatrixFromVar, matrix = matrix, analyse_type = 'splitvar', parametres = {'pathout': matrix.pathout.dirout}, dlgnb = 3)
1069         #matrix = self.tree.getmatrix()
1070
1071     def OnSimiTxt(self, evt, corpus = None) :
1072         try :
1073             #self.Text = SimiTxt(self)
1074             if corpus is None :
1075                 corpus = self.tree.getcorpus()
1076             self.Text = SimiTxt(self, corpus, parametres = {'type': 'simitxt'}, dlg = 3)
1077             if self.Text.val == wx.ID_OK :
1078                 PlaySound(self)
1079         except :
1080             BugReport(self)
1081
1082     def OnWordCloud(self, evt, corpus = None) :
1083         try :
1084             if corpus is None :
1085                 corpus = self.tree.getcorpus()
1086             self.Text = WordCloud(self, corpus, parametres = {'type' : 'wordcloud'}, dlg = 3)
1087             if self.Text.val == wx.ID_OK :
1088                 PlaySound(self)
1089         except :
1090             BugReport(self)
1091
1092     def OnClusterCloud(self, corpus, parametres = None) :
1093         self.Text = ClusterCloud(self, corpus, parametres = parametres, dlg = 3)
1094
1095     def OnAFCM(self, event):
1096         try:
1097             DoAFCM(self)
1098         except:
1099             BugReport(self)
1100
1101     def OnTextStat(self, event, corpus = None):
1102         try:
1103             if corpus is None :
1104                 corpus = self.tree.getcorpus()
1105             self.Text = Stat(self, corpus, parametres = {'type': 'stat'}, dlg = 7)
1106             if self.Text.val == wx.ID_OK :
1107                 PlaySound(self)
1108         except:
1109             BugReport(self)
1110
1111     def OnTextSpec(self, event, corpus = None):
1112         try:
1113             #self.Text = AsLexico(self)
1114             if corpus is None :
1115                 corpus = self.tree.getcorpus()
1116             self.Text = Lexico(self, corpus, parametres = {'type' : 'spec'}, dlg = 3)
1117             if self.Text.val == wx.ID_OK :
1118                 PlaySound(self)
1119         except:
1120             BugReport(self)
1121
1122     def OnTextLabbe(self, event, corpus = None):
1123         try:
1124             if corpus is None :
1125                 corpus = self.tree.getcorpus()
1126             self.Text = DistLabbe(self, corpus, parametres = {'type' : 'labbe'}, dlg = 3)
1127             if self.Text.val == wx.ID_OK :
1128                 PlaySound(self)
1129         except:
1130             BugReport(self)
1131
1132     def OnTextAfcm(self, event):
1133         try:
1134             AfcUci(self)
1135             PlaySound(self)
1136         except:
1137             BugReport(self)
1138
1139     def import_factiva_xml(self,event):
1140         try :
1141             ImportFactiva(self, 'xml')
1142         except :
1143             BugReport(self)
1144
1145     def import_factiva_mail(self, evt) :
1146         try :
1147             ImportFactiva(self, 'mail')
1148         except :
1149             BugReport(self)
1150
1151     def import_factiva_txt(self, evt) :
1152         try :
1153             ImportFactiva(self, 'txt')
1154         except :
1155             BugReport(self)
1156
1157     def OnImportTXM(self, evt) :
1158         try :
1159             ImportFactiva(self, 'txm')
1160         except :
1161             BugReport(self)
1162
1163     def OnImportEuropress(self, evt) :
1164         try :
1165             ImportFactiva(self, 'euro')
1166         except :
1167             BugReport(self)
1168
1169     def OnImportDMI(self, evt):
1170         ImportDMI(self, {})
1171
1172     def OnExportMeta(self, evt, corpus = None):
1173         if corpus is None :
1174             corpus = self.tree.getcorpus()
1175         try :
1176             ExportMetaTable(self, corpus)
1177         except :
1178             BugReport(self)
1179
1180     def ExtractTools(self, evt) :
1181         ID = evt.GetId()
1182         if ID == self.ID_splitvar :
1183             Extract(self, 'splitvar')
1184         elif ID == self.ID_extractmod :
1185             Extract(self, 'mods')
1186         elif ID == self.ID_extractthem :
1187             Extract(self, 'them')
1188
1189     def OnTextReinert(self, event, corpus = None):
1190         try:
1191             #RunAnalyse(self, corpus, Alceste, OptAlceste)
1192             if corpus is None :
1193                 corpus = self.tree.getcorpus()
1194             self.Text = Reinert(self, corpus, parametres = {'type': 'alceste'}, dlg = 6)
1195             if self.Text.val == wx.ID_OK:
1196                 PlaySound(self)
1197         except:
1198             BugReport(self)
1199
1200     def OnPamSimple(self, event, corpus = None):
1201         try:
1202             if corpus is None :
1203                 corpus = self.tree.getcorpus()
1204             self.Text = AnalysePam(self, corpus, parametres = {'type' : 'pamtxt'}, dlg = 6)
1205             if self.Text.val == wx.ID_OK:
1206                 PlaySound(self)
1207         except:
1208             BugReport(self)
1209
1210     def SimiCluster(self, parametres = {}, fromprof = False, tableau = None) :
1211         self.analyse_matrix(DoSimi, parametres = parametres, analyse_type = 'simiclustermatrix', matrix = tableau, dlgnb = 5)
1212
1213 #    def OnSimi(self,evt):
1214 #        try :
1215 #            self.res = DoSimi(self, param = None)
1216             #self.res = Verges(self)
1217 #            if self.res.val == wx.ID_OK :
1218 #                PlaySound(self)
1219 #        except :
1220 #            BugReport(self)
1221
1222     def OnHelp(self, event):
1223         webbrowser.open('http://www.iramuteq.org/documentation')
1224
1225     def OnPref(self, event):
1226         dlg = PrefDialog(self)
1227         dlg.CenterOnParent()
1228         self.val = dlg.ShowModal()
1229         dlg.Destroy()
1230
1231     def Upgrade(self) :
1232         if self.check_update:
1233             NewVersion(self)
1234         else:
1235             print('pas de verif')
1236         #IsNew(self)
1237         #CheckRPackages(self)
1238
1239     def OnOpenFromCmdl(self):
1240         truepath = True
1241         if options.filename :
1242             if os.path.exists(options.filename):
1243                 self.filename = os.path.abspath(options.filename)
1244             else:
1245                 truepath = False
1246         elif args :
1247             if os.path.exists(os.path.realpath(args[0])):
1248                 self.filename = os.path.abspath(os.path.realpath(args[0]))
1249             else:
1250                 truepath = False
1251         else:
1252             return
1253         if truepath :
1254             if os.path.splitext(self.filename)[1] in ['.csv', '.xls', '.ods']:
1255                 self.tableau = Tableau(self, self.filename)
1256                 val = get_table_param(self, self.filename)
1257                 if val == wx.ID_OK :
1258                     self.tableau.make_content()
1259                     OpenAnalyse(self, self.tableau.parametres)
1260                     self.tree.OnItemAppend(self.tableau.parametres)
1261                 #get_table_param(self, self.filename)
1262                 #self.tableau.make_content()
1263                 #self.tableau.show_tab()
1264                 #open_data(self, self.filename)
1265             elif os.path.splitext(self.filename)[1] == '.txt':
1266                 self.OpenText()
1267             elif os.path.splitext(self.filename)[1] == '.ira' :
1268                 #self.corpus = Corpus(self)
1269                 #self.Text = OpenAnalyse(self, self.filename)
1270                 OpenAnalyse(self, self.filename)
1271         if not truepath:
1272             print('This file does not exist')
1273
1274
1275 #--------------------------------------------------------------------
1276 # contenu de l'ecran d'accueil
1277 # appelé seulement dans l'initialisation de IraFrame
1278 #--------------------------------------------------------------------
1279 class IntroPanel(wx.Panel):
1280     def __init__(self, parent):
1281         wx.Panel.__init__(self, parent)
1282         #col = randint(0, 255)
1283         #col1 = randint(0,255)
1284         #col2 = randint(0,255)
1285         #col = 57
1286         col = 161
1287         col1 = 198
1288         col2 = 224
1289         bckgrdcolor = wx.Colour(col, col1, col2)
1290         self.SetBackgroundColour(bckgrdcolor)
1291         txtcolour = wx.Colour(250, 250, 250)
1292         linkcolor = wx.Colour(255, 0, 0)
1293         sizer1 = wx.BoxSizer(wx.VERTICAL)
1294         sizer2 = wx.BoxSizer(wx.VERTICAL)
1295         sizer4 = wx.BoxSizer(wx.HORIZONTAL)
1296         grid_sizer_1 = wx.FlexGridSizer(1, 4, 0, 0)
1297         grid_sizer_3 = wx.FlexGridSizer(1, 4, 0, 0)
1298         grid_sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
1299         iralink = hl.HyperLinkCtrl(self,
1300             wx.ID_ANY,
1301             "http://www.iramuteq.org",
1302             URL="http://www.iramuteq.org")
1303         iralink.SetColours(linkcolor, linkcolor, "RED")
1304         iralink.SetBackgroundColour(bckgrdcolor)
1305         iralink.EnableRollover(True)
1306         iralink.SetUnderlines(False, False, True)
1307         iralink.SetBold(True)
1308         iralink.UpdateLink()
1309         PanelPres = wx.Panel(self)
1310         bckgrdcolor = wx.Colour(randint(0, 255), randint(0, 255), randint(0, 255))
1311         PanelPres.SetBackgroundColour(bckgrdcolor)
1312         label_1 = wx.StaticText(self, -1, "IRaMuTeQ", size=(-1, -1))
1313         label_1.SetFont(wx.Font(46,
1314             wx.FONTFAMILY_TELETYPE,
1315             wx.FONTSTYLE_NORMAL,
1316             wx.FONTWEIGHT_BOLD,
1317             0,
1318             "Purisa"))
1319         label_1.SetForegroundColour(wx.RED)
1320         iraicone = wx.Image(os.path.join(ImagePath,'iraicone100x100.png'), wx.BITMAP_TYPE_ANY).ConvertToBitmap()
1321         but_ira = wx.StaticBitmap(self, -1, bitmap = iraicone)
1322         label2 = wx.StaticText(PanelPres, -1 , '\nVersion ' + ConfigGlob.get('DEFAULT', 'version') + '\n')
1323         label2.SetForegroundColour(txtcolour)
1324         label2.SetBackgroundColour(bckgrdcolor)
1325         self.hyper2 = hl.HyperLinkCtrl(PanelPres, wx.ID_ANY, "REPERE", URL="http://repere.no-ip.org/")
1326         self.hyper2.SetColours(linkcolor, linkcolor, "RED")
1327         self.hyper2.SetBackgroundColour(bckgrdcolor)
1328         self.hyper2.EnableRollover(True)
1329         self.hyper2.SetUnderlines(False, False, True)
1330         self.hyper2.SetBold(True)
1331         self.hyper2.UpdateLink()
1332         label_lerass = wx.StaticText(PanelPres, -1, 'Laboratoire ')
1333         label_lerass.SetForegroundColour(txtcolour)
1334         label_lerass.SetBackgroundColour(bckgrdcolor)
1335         self.hyper_lerass = hl.HyperLinkCtrl(PanelPres, -1, 'LERASS', URL="http://www.lerass.com")
1336         self.hyper_lerass.SetColours(linkcolor, linkcolor, "RED")
1337         self.hyper_lerass.SetBackgroundColour(bckgrdcolor)
1338         self.hyper_lerass.EnableRollover(True)
1339         self.hyper_lerass.SetUnderlines(False, False, True)
1340         self.hyper_lerass.SetBold(True)
1341         self.hyper_lerass.UpdateLink()
1342         blank = wx.StaticText(PanelPres, -1, '\n')
1343         blank1 = wx.StaticText(PanelPres, -1, '\n')
1344         labellicence = wx.StaticText(PanelPres, -1, _("License GNU GPL"))
1345         labellicence.SetForegroundColour(txtcolour)
1346         labellicence.SetBackgroundColour(bckgrdcolor)
1347         labelcopy = wx.StaticText(PanelPres, -1, ConfigGlob.get('DEFAULT', 'copyright'))
1348         labelcopy.SetForegroundColour(txtcolour)
1349         labelcopy.SetBackgroundColour(bckgrdcolor)
1350         python_img = wx.Image(os.path.join(ImagePath,'python-logo.jpg'), wx.BITMAP_TYPE_ANY).ConvertToBitmap()
1351         r_img = wx.Image(os.path.join(ImagePath,'Rlogo.jpg'), wx.BITMAP_TYPE_ANY).ConvertToBitmap()
1352         lexique_img = wx.Image(os.path.join(ImagePath,'LexTexte4.jpg'), wx.BITMAP_TYPE_ANY).ConvertToBitmap()
1353         but_python = wx.BitmapButton(self, -1, python_img)
1354         but_lexique = wx.BitmapButton(self, -1, lexique_img)
1355         but_r = wx.BitmapButton(self, -1, r_img)
1356         self.Bind(wx.EVT_BUTTON, self.OnPython, but_python)
1357         self.Bind(wx.EVT_BUTTON, self.OnLexique, but_lexique)
1358         self.Bind(wx.EVT_BUTTON, self.OnR, but_r)
1359         grid_sizer_1.Add(self.hyper2, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 0)
1360         grid_sizer_3.Add(label_lerass, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 0)
1361         grid_sizer_3.Add(self.hyper_lerass, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 0)
1362         sizer4.Add(label_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5)
1363         sizer2.Add(label2, 0, wx.ALIGN_CENTER, 5)
1364         sizer2.Add(wx.StaticText(PanelPres, -1, ''), 0, wx.ALIGN_CENTER, 5)
1365         sizer2.Add(wx.StaticText(PanelPres, -1, ''), 0, wx.ALIGN_CENTER, 5)
1366         sizer2.Add(grid_sizer_3, 0, wx.ALIGN_CENTER, 5)
1367         sizer2.Add(wx.StaticText(PanelPres, -1, ' '), 0, wx.ALIGN_CENTER, 5)
1368         sizer2.Add(grid_sizer_1, 0, wx.ALIGN_CENTER, 5)
1369         sizer2.Add(labellicence, 0, wx.ALIGN_CENTER, 5)
1370         sizer2.Add(labelcopy, 0, wx.ALIGN_CENTER, 5)
1371         sizer1.Add(sizer4, 2, wx.ALIGN_CENTER_HORIZONTAL, 0)
1372         sizer1.Add(but_ira, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5)
1373         sizer1.Add(iralink, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_TOP, 5)
1374         sizer2.Add(wx.StaticText(PanelPres, -1, ''), 0, wx.ALIGN_CENTER, 10)
1375         PanelPres.SetSizer(sizer2)
1376         grid_sizer_2.Add(but_python, 1, wx.ALIGN_BOTTOM)
1377         grid_sizer_2.Add(but_lexique, 1, wx.ALIGN_BOTTOM)
1378         grid_sizer_2.Add(but_r, 1,  wx.ALIGN_BOTTOM)
1379         sizer1.Add(PanelPres, 0, wx.EXPAND |wx.ALL, 10)
1380         sizer1.Add(grid_sizer_2, 2, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 1)
1381         self.SetSizer(sizer1)
1382         sizer1.Fit(self)
1383
1384     def OnPython(self,evt):
1385         webbrowser.open('http://www.python.org')
1386
1387     def OnLexique(self,evt):
1388         webbrowser.open('http://www.lexique.org')
1389
1390     def OnR(self,evt):
1391         webbrowser.open('http://www.r-project.org')
1392
1393
1394 #--------------------------------------------------------------------
1395 # ecran d'accueil
1396 # appelé seulement par MyApp
1397 #--------------------------------------------------------------------
1398 class MySplashScreen(wx.adv.SplashScreen):
1399
1400     def __init__(self):
1401         bmp = wx.Image(os.path.join(ImagePath, 'splash.png')).ConvertToBitmap()
1402         wx.adv.SplashScreen.__init__(self, bmp,
1403             wx.adv.SPLASH_CENTRE_ON_SCREEN |
1404             wx.adv.SPLASH_TIMEOUT,
1405             1000,
1406             None,
1407             -1)
1408         self.Bind(wx.EVT_CLOSE, self.OnClose)
1409         self.fc = wx.CallLater(1, self.ShowMain)
1410
1411     def OnClose(self, evt):
1412         evt.Skip()
1413         self.Hide()
1414         if self.fc.IsRunning():
1415             self.fc.Stop()
1416             self.ShowMain()
1417
1418     def ShowMain(self):
1419         displaySize = wx.DisplaySize()
1420         w = displaySize[0]/1.2
1421         h = displaySize[1]/1.2
1422         frame = IraFrame(None, -1, "IRaMuTeQ " + ConfigGlob.get('DEFAULT', 'version'), size=(w, h))
1423         frame.Show()
1424         frame.finish_init()
1425         frame.Upgrade()
1426         frame.OnOpenFromCmdl()
1427         #if self.fc.IsRunning():
1428         #    self.Raise()
1429         #wx.CallAfter(frame.ShowTip)
1430
1431
1432 class MyApp(wx.App):
1433
1434     def OnInit(self):
1435         """
1436         Create and show the splash screen.  It will then create and show
1437         the main frame when it is time to do so.
1438         """
1439         wx.SystemOptions.SetOption("mac.window-plain-transition", 1)
1440         self.SetAppName("Iramuteq")
1441         splash = MySplashScreen()
1442         splash.Show()
1443         return True
1444
1445 def main():
1446     app = MyApp(False)
1447     app.MainLoop()
1448
1449 if __name__ == '__main__':
1450     __name__ = 'Main'
1451     main()