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