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                 if os.path.exists(self.AppliPath + '\\R\\R') :
704                     BestRPath = self.AppliPath + '\\R\\R\\bin\\x64\\R.exe'
705                 else :
706                     BestRPath = FindRPAthWin32()
707             else:
708                 BestRPath = FindRPathNix()
709             if BestRPath:
710                 self.PathPath.set('PATHS', 'rpath', BestRPath)
711                 with open(ConfigPath['path'], 'w') as f :
712                     self.PathPath.write(f)
713         else:
714             BestRPath = True
715         if BestRPath :
716             self.RPath = self.PathPath.get('PATHS', 'rpath')
717             if New :
718                 CheckRPackages(self)
719             if not RLibsAreInstalled(self) :
720                 CheckRPackages(self)
721         else :
722             msg = '\n'.join([_("Can't find R executable"), _("If R is not installed, get it from http://www.r-project.org."),
723                              _("If R is installed, report its path in Preferences."),
724                              _("IRaMuTeQ does not work without R.")])
725             dlg = wx.MessageDialog(self, msg, _("Problem"), wx.OK | wx.ICON_WARNING)
726             dlg.CenterOnParent()
727             if dlg.ShowModal() in [wx.ID_NO, wx.ID_CANCEL]:
728                 pass
729             dlg.Destroy()
730
731     def OnVerif(self, evt) :
732         pack = CheckRPackages(self)
733         if pack :
734             dlg = wx.MessageDialog(self, _("Installation OK"), _("Installation"), wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP)
735             dlg.CenterOnParent()
736             if dlg.ShowModal() in [wx.ID_NO, wx.ID_CANCEL]:
737                 evt.Veto()
738
739     # appelé par des fonctions de ce fichier et tree.py : OnSelChanged
740     # vu comme elle est écrite, impossible de gérer
741     # l'affichage/masquage des toolbars en fonction du contexte
742     def ShowMenu(self, menu, Show=True):
743         if menu == 'text' :
744             menu_pos = 4
745             if Show :
746                 self._mgr.GetPane('tb_text').Show()
747             else :
748                 self._mgr.GetPane('tb_text').Hide()
749         elif menu == 'matrix' :
750             menu_pos = 3
751             if Show :
752                 self._mgr.GetPane('tb_mat').Show()
753             else :
754                 self._mgr.GetPane('tb_mat').Hide()
755         elif menu == 'view' :
756             menu_pos = 2
757         else :
758             menu_pos = None
759         if not menu_pos is None :
760             self.mb.EnableTop(menu_pos, Show)
761             self.mb.Refresh()
762         #self._mgr.Update()
763
764     #--------------------------------------------------------------------
765     # fin de __init__ du wx.Frame
766     #--------------------------------------------------------------------
767
768     # evenement attaché au bouton de fermeture des fenetres ou onglets ?
769     def OnClose(self, event):
770         print('onclose Iramuteq')
771         with open(self.ConfigPath['path'], 'w') as f :
772             self.PathPath.write(f)
773         self._mgr.UnInit()
774         del self._mgr
775         self.Destroy()
776
777     # evenement attaché au menu 'ouvrir matrice'
778     def OnOpenData(self, event):
779         print('on open data')
780         inputname, self.input_path = OnOpen(self, "Data")
781         if inputname:
782             # filename = self.input_path[0]
783             self.tableau = Tableau(self,os.path.abspath(self.input_path[0]))
784             val = get_table_param(self, self.input_path[0])
785             if val == wx.ID_OK :
786                 busy = wx.BusyInfo(_("Please wait..."), self)
787                 wx.SafeYield()
788                 try :
789                     self.tableau.make_content()
790                     OpenAnalyse(self, self.tableau.parametres)
791                     self.tree.OnItemAppend(self.tableau.parametres)
792                     del busy
793                 except :
794                     del busy
795                     BugReport(self)
796                 # self.tableau.show_tab()
797
798     # evenement attaché au menu 'ouvrir analyse'
799     def OnOpenAnalyse(self, event):
800         print('on open analyse')
801         self.AnalysePath = OnOpen(self, "Analyse")
802         if self.AnalysePath :
803             OpenAnalyse(self, self.AnalysePath[1][0], True)
804             self.ShowMenu('view')
805
806     # evenement attaché au menu 'ouvrir un texte/corpus'
807     def OnOpenText(self, event):
808         print('on open text')
809         inputname, self.input_path = OnOpen(self, "Texte")
810         self.filename = self.input_path[0]
811         if inputname:
812             self.OpenText()
813
814     # evenement attaché au menu 'ouvrir analyse'
815     def OnSubText(self, evt, corpus = None, parametres = None):
816         print('on sub text')
817         if corpus is None :
818             corpus = self.tree.getcorpus()
819         if evt.GetId() == ID_Subtxtfrommeta :
820             parametres = {'frommeta' : True}
821         elif evt.GetId() == ID_Subtxtfromthem :
822             parametres = {'fromtheme' : True}
823         builder = SubBuilder(self, corpus, parametres)
824         if builder.res == wx.ID_OK :
825             busy = wx.BusyInfo(_("Please wait..."), self)
826             wx.SafeYield()
827             corpus = builder.doanalyse()
828             self.history.add(corpus.parametres)
829             OpenAnalyse(self, corpus.parametres)
830             self.tree.OnItemAppend(corpus.parametres)
831             del busy
832
833     # action d'ouverture d'un texte
834     def OpenText(self):
835         print('open text')
836         builder =  Builder(self, 5)
837         if builder.res == wx.ID_OK :
838             try :
839                 corpus = builder.doanalyse()
840                 self.history.add(corpus.parametres)
841                 self.tree.OnItemAppend(corpus.parametres)
842                 OpenAnalyse(self, corpus.parametres)
843             except :
844                 builder.dlg.Destroy()
845                 BugReport(self)
846             else :
847                 count = 1
848                 keepGoing = builder.dlg.Update(count, "Lecture du fichier")
849                 self.ShowMenu('view')
850                 self.ShowMenu('text')
851                 self.ShowMenu('matrix', False)
852                 self.type = "Texte"
853                 self.DataTxt = False
854                 self.Text = ''
855                 count += 1
856                 keepGoing = builder.dlg.Update(count, "Chargement du dictionnaire")
857                 builder.dlg.Destroy()
858
859     # evenement attaché au menu 'quitter'
860     def OnExit(self, event):
861         self.Close()
862
863     # evenement attaché au menu 'à propos'
864     def OnAbout(self, event):
865         print('on about')
866         info = wx.adv.AboutDialogInfo()
867         info.Name = ConfigGlob.get('DEFAULT', 'name')
868         info.Version = ConfigGlob.get('DEFAULT', 'version')
869         info.Copyright = ConfigGlob.get('DEFAULT', 'copyright')
870         info.Translators = ConfigGlob.get('DEFAULT', 'translators').split(';')
871         info.Description = """
872 Interface de R pour les Analyses Multidimensionnelles
873 de Textes et de Questionnaires
874
875 Un logiciel libre
876 construit avec des logiciels libres.
877
878 Laboratoire LERASS
879
880 REPERE
881 """
882         info.WebSite = ("http://www.iramuteq.org", "Site web IRaMuTeQ")
883         dev = ConfigGlob.get('DEFAULT', 'dev').split(';')
884         info.Developers = dev
885         info.License = """Iramuteq est un logiciel libre ; vous pouvez le diffuser et/ou le modifier
886 suivant les termes de la Licence Publique Générale GNU telle que publiée 
887 par la Free Software Foundation ; soit la version 2 de cette licence, 
888 soit (à votre convenance) une version ultérieure.
889
890 Iramuteq est diffusé dans l'espoir qu'il sera utile, 
891 mais SANS AUCUNE GARANTIE ; sans même une garantie implicite 
892 de COMMERCIALISATION ou d'ADÉQUATION À UN USAGE PARTICULIER. 
893 Voyez la Licence Publique Générale GNU pour plus de détails.
894
895 Vous devriez avoir reçu une copie de la Licence Publique Générale GNU
896 avec Iramuteq ; sinon, veuillez écrire à la Free Software Foundation,
897 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, États-Unis."""
898         wx.adv.AboutBox(info)
899
900     # appelé seulement pour l'initialisation de la fenetre principale de Iramuteq
901     def GetDockArt(self):
902         return self._mgr.GetArtProvider()
903
904     # appelé seulement pour l'initialisation de la fenetre principale de Iramuteq
905     def DoUpdate(self):
906         self._mgr.Update()
907
908     # action ou évènement ?
909     def OnPageChanged(self, event) :
910         new = event.GetSelection()
911         nobject = event.GetEventObject()
912         parent = nobject.GetParent()
913         if isinstance(parent, IraFrame) :
914             npage = self.nb.GetPage(new)
915             if 'parametres' in dir(npage) :
916                 #self.tree.GiveFocus(uuid=npage.parametres['uuid'])
917                 if npage.parametres.get('matrix', False) :
918                     self.ShowMenu('text', False)
919                     self.ShowMenu('matrix', True)
920                 elif npage.parametres.get('corpus', False) :
921                     self.ShowMenu('text')
922                     self.ShowMenu('matrix', False)
923         #self._mgr.Update()
924         #wx.CallAfter(self.nb.SendSizeEvent)
925         #self.Refresh()
926
927     # action ou évènement ?
928     def OnCloseTab(self, evt):
929         #log.info('Closing tab %s' % str(evt.GetEventObject()))
930         ctrl = evt.GetEventObject()
931         if isinstance(ctrl.GetParent(), aui.AuiNotebook) or isinstance(ctrl.GetParent(), wx.Panel):
932             notebook = True
933         else :
934             notebook = False
935         page = self.nb.GetPage(self.nb.GetSelection())
936         if 'parametres' in dir(page) and isinstance(ctrl.GetParent(), IraFrame) :
937             self.history.rmtab(page.parametres)
938             self.tree.CloseItem(uuid = page.parametres['uuid'])
939         TabTitle = self.nb.GetPageText(self.nb.GetSelection())
940         if self.nb.GetPageCount() == 1 and not notebook :
941             self.LastTabClose()
942
943     # action ou évènement ?
944     def LastTabClose(self) :
945         if self.nb.GetPageCount() == 1 :
946             if self.DataTxt :
947                 self.ShowAPane("Text")
948             elif self.DataPop :
949                 self.ShowAPane("Data")
950             else :
951                 self.ShowAPane("Intro_Text")
952
953     # action ou évènement ?
954     def GetStartPosition(self):
955         self.x = self.x + 20
956         x = self.x
957         pt = self.ClientToScreen(wx.Point(0, 0))
958         return wx.Point(pt.x + x, pt.y + x)
959
960     # action ou évènement ?
961     def ShowAPane(self, panel):
962         for pane in self._mgr.GetAllPanes() :
963             if not pane.IsToolbar() and pane.name != 'lefttree':
964                 pane.Hide()
965         self._mgr.GetPane(panel).Show()
966         self._mgr.Update()
967         print('show a pane refresh')
968         wx.CallAfter(self.nb.SendSizeEvent)
969         self.Refresh()
970
971     # action ou évènement ?
972     def OnAcceuil(self, event):
973         self.ShowAPane("Intro_Text")
974         event.Skip()
975
976     # action ou évènement ?
977     def CreateHTMLCtrl(self):
978         ctrl = wx.html.HtmlWindow(self, -1, wx.DefaultPosition, wx.Size(400, 300))
979         if "gtk2" in wx.PlatformInfo:
980             ctrl.SetStandardFonts()
981         ctrl.SetPage("text")
982         return ctrl
983
984     # action ou évènement ?
985     def ShowTab(self, evt):
986         self.ShowAPane("Tab_content")
987
988     ################################################################
989     #debut des analyses
990     ################################################################
991     def analyse_matrix(self, analyse, analyse_type = '', matrix = None, parametres = None, dlgnb = 1):
992         if matrix is None :
993             matrix = self.tree.getmatrix()
994         if parametres is not None :
995             parametres['type'] = analyse_type
996         else :
997             parametres = {'type' : analyse_type}
998         try :
999             #print 'plus de bug@@@@@@@@@@@@@@@@@@@@@@'
1000             analyse(self, matrix, parametres = parametres, dlg = dlgnb)
1001         except:
1002             BugReport(self)
1003
1004     def OnFreq(self, event, matrix = None):
1005         self.analyse_matrix(Frequences, analyse_type = 'freq', matrix = matrix, dlgnb = 3)
1006
1007     def OnFreqMulti(self, event, matrix = None):
1008         self.analyse_matrix(FreqMultiple, analyse_type = 'freqmulti', matrix = matrix, dlgnb = 3)
1009
1010     def OnChi2(self, event, matrix = None):
1011         self.analyse_matrix(ChiSquare, matrix = matrix, analyse_type = 'chi2', dlgnb = 3)
1012
1013     def OnChi2McNemar(self, event, matrix = None):
1014         self.analyse_matrix(McNemar, matrix = matrix, analyse_type = 'chi2mcnemar', dlgnb = 3)
1015
1016     def OnSimiTab(self, event, matrix = None):
1017         self.analyse_matrix(DoSimi, matrix = matrix, analyse_type = 'simimatrix', dlgnb = 5)
1018
1019     def OnCHDReinert(self, event, matrix = None):
1020         #if matrix is None :
1021         #    matrix = self.tree.getmatrix()
1022         #AnalyseQuest(self, matrix, parametres = {'type' : 'reinertmatrix'}, dlg = 3)
1023         self.analyse_matrix(AnalyseQuest, matrix = matrix, analyse_type = 'reinertmatrix', dlgnb = 5)
1024
1025     def OnStudent(self, event):
1026         try:
1027             MakeStudent(self)
1028         except:
1029             BugReport(self)
1030
1031     def OnRCode(self, event):
1032         try:
1033             InputText(self)
1034         except:
1035             BugReport(self)
1036
1037     def OnCHDSIM(self, event):
1038         try:
1039             chdsim = ChdCluster(self)
1040             if chdsim.val == wx.ID_OK:
1041                 PlaySound(self)
1042         except:
1043             BugReport(self)
1044
1045 #     def OnCHDReinert(self, event):
1046 #         try:
1047 #          #   print('PLUS DE BUG SUR ALCESTE QUESTIONNAIRE')
1048 #             self.quest = AnalyseQuest(self)
1049 #             if self.quest.val == wx.ID_OK:
1050 #                 PlaySound(self)
1051 #         except:
1052 #             BugReport(self)
1053
1054     def OnMergeGraph(self, evt):
1055         #FIXME
1056         AnalyseMerge(self, {'type': 'merge', 'fileout' : '/tmp/test.txt'}, dlg = 5)
1057
1058     def OnMergeClusters(self, evt) :
1059         print('on merge clusters')
1060         builder = MergeClusters(self, {})
1061         if builder.res == wx.ID_OK :
1062             busy = wx.BusyInfo(_("Please wait..."), self)
1063             wx.SafeYield()
1064             corpus = builder.doanalyse()
1065             self.history.add(corpus.parametres)
1066             OpenAnalyse(self, corpus.parametres)
1067             self.tree.OnItemAppend(corpus.parametres)
1068             del busy
1069
1070     def OnProto(self, evt, matrix = None) :
1071         self.analyse_matrix(Prototypical, matrix = matrix, analyse_type = 'proto', dlgnb = 3) 
1072         #Prototypical(self, {'type' : 'proto'})
1073
1074     def OnSplitVar(self, evt, matrix = None):
1075         if matrix is None :
1076             matrix = self.tree.getmatrix()
1077         self.analyse_matrix(SplitMatrixFromVar, matrix = matrix, analyse_type = 'splitvar', parametres = {'pathout': matrix.pathout.dirout}, dlgnb = 3)
1078         #matrix = self.tree.getmatrix()
1079
1080     def OnSimiTxt(self, evt, corpus = None) :
1081         try :
1082             #self.Text = SimiTxt(self)
1083             if corpus is None :
1084                 corpus = self.tree.getcorpus()
1085             self.Text = SimiTxt(self, corpus, parametres = {'type': 'simitxt'}, dlg = 3)
1086             if self.Text.val == wx.ID_OK :
1087                 PlaySound(self)
1088         except :
1089             BugReport(self)
1090
1091     def OnWordCloud(self, evt, corpus = None) :
1092         try :
1093             if corpus is None :
1094                 corpus = self.tree.getcorpus()
1095             self.Text = WordCloud(self, corpus, parametres = {'type' : 'wordcloud'}, dlg = 3)
1096             if self.Text.val == wx.ID_OK :
1097                 PlaySound(self)
1098         except :
1099             BugReport(self)
1100
1101     def OnClusterCloud(self, corpus, parametres = None) :
1102         self.Text = ClusterCloud(self, corpus, parametres = parametres, dlg = 3)
1103
1104     def OnAFCM(self, event):
1105         try:
1106             DoAFCM(self)
1107         except:
1108             BugReport(self)
1109
1110     def OnTextStat(self, event, corpus = None):
1111         try:
1112             if corpus is None :
1113                 corpus = self.tree.getcorpus()
1114             self.Text = Stat(self, corpus, parametres = {'type': 'stat'}, dlg = 7)
1115             if self.Text.val == wx.ID_OK :
1116                 PlaySound(self)
1117         except:
1118             BugReport(self)
1119
1120     def OnTextSpec(self, event, corpus = None):
1121         try:
1122             #self.Text = AsLexico(self)
1123             if corpus is None :
1124                 corpus = self.tree.getcorpus()
1125             self.Text = Lexico(self, corpus, parametres = {'type' : 'spec'}, dlg = 3)
1126             if self.Text.val == wx.ID_OK :
1127                 PlaySound(self)
1128         except:
1129             BugReport(self)
1130
1131     def OnTextLabbe(self, event, corpus = None):
1132         try:
1133             if corpus is None :
1134                 corpus = self.tree.getcorpus()
1135             self.Text = DistLabbe(self, corpus, parametres = {'type' : 'labbe'}, dlg = 3)
1136             if self.Text.val == wx.ID_OK :
1137                 PlaySound(self)
1138         except:
1139             BugReport(self)
1140
1141     def OnTextAfcm(self, event):
1142         try:
1143             AfcUci(self)
1144             PlaySound(self)
1145         except:
1146             BugReport(self)
1147
1148     def import_factiva_xml(self,event):
1149         try :
1150             ImportFactiva(self, 'xml')
1151         except :
1152             BugReport(self)
1153
1154     def import_factiva_mail(self, evt) :
1155         try :
1156             ImportFactiva(self, 'mail')
1157         except :
1158             BugReport(self)
1159
1160     def import_factiva_txt(self, evt) :
1161         try :
1162             ImportFactiva(self, 'txt')
1163         except :
1164             BugReport(self)
1165
1166     def OnImportTXM(self, evt) :
1167         try :
1168             ImportFactiva(self, 'txm')
1169         except :
1170             BugReport(self)
1171
1172     def OnImportEuropress(self, evt) :
1173         try :
1174             ImportFactiva(self, 'euro')
1175         except :
1176             BugReport(self)
1177
1178     def OnImportDMI(self, evt):
1179         ImportDMI(self, {})
1180
1181     def OnExportMeta(self, evt, corpus = None):
1182         if corpus is None :
1183             corpus = self.tree.getcorpus()
1184         try :
1185             ExportMetaTable(self, corpus)
1186         except :
1187             BugReport(self)
1188
1189     def ExtractTools(self, evt) :
1190         ID = evt.GetId()
1191         if ID == self.ID_splitvar :
1192             Extract(self, 'splitvar')
1193         elif ID == self.ID_extractmod :
1194             Extract(self, 'mods')
1195         elif ID == self.ID_extractthem :
1196             Extract(self, 'them')
1197
1198     def OnTextReinert(self, event, corpus = None):
1199         try:
1200             #RunAnalyse(self, corpus, Alceste, OptAlceste)
1201             if corpus is None :
1202                 corpus = self.tree.getcorpus()
1203             self.Text = Reinert(self, corpus, parametres = {'type': 'alceste'}, dlg = 6)
1204             if self.Text.val == wx.ID_OK:
1205                 PlaySound(self)
1206         except:
1207             BugReport(self)
1208
1209     def OnPamSimple(self, event, corpus = None):
1210         try:
1211             if corpus is None :
1212                 corpus = self.tree.getcorpus()
1213             self.Text = AnalysePam(self, corpus, parametres = {'type' : 'pamtxt'}, dlg = 6)
1214             if self.Text.val == wx.ID_OK:
1215                 PlaySound(self)
1216         except:
1217             BugReport(self)
1218
1219     def SimiCluster(self, parametres = {}, fromprof = False, tableau = None) :
1220         self.analyse_matrix(DoSimi, parametres = parametres, analyse_type = 'simiclustermatrix', matrix = tableau, dlgnb = 5)
1221
1222 #    def OnSimi(self,evt):
1223 #        try :
1224 #            self.res = DoSimi(self, param = None)
1225             #self.res = Verges(self)
1226 #            if self.res.val == wx.ID_OK :
1227 #                PlaySound(self)
1228 #        except :
1229 #            BugReport(self)
1230
1231     def OnHelp(self, event):
1232         webbrowser.open('http://www.iramuteq.org/documentation')
1233
1234     def OnPref(self, event):
1235         dlg = PrefDialog(self)
1236         dlg.CenterOnParent()
1237         self.val = dlg.ShowModal()
1238         dlg.Destroy()
1239
1240     def Upgrade(self) :
1241         if self.check_update:
1242             NewVersion(self)
1243         else:
1244             print('pas de verif')
1245         #IsNew(self)
1246         #CheckRPackages(self)
1247
1248     def OnOpenFromCmdl(self):
1249         truepath = True
1250         if options.filename :
1251             if os.path.exists(options.filename):
1252                 self.filename = os.path.abspath(options.filename)
1253             else:
1254                 truepath = False
1255         elif args :
1256             if os.path.exists(os.path.realpath(args[0])):
1257                 self.filename = os.path.abspath(os.path.realpath(args[0]))
1258             else:
1259                 truepath = False
1260         else:
1261             return
1262         if truepath :
1263             if os.path.splitext(self.filename)[1] in ['.csv', '.xls', '.ods']:
1264                 self.tableau = Tableau(self, self.filename)
1265                 val = get_table_param(self, self.filename)
1266                 if val == wx.ID_OK :
1267                     self.tableau.make_content()
1268                     OpenAnalyse(self, self.tableau.parametres)
1269                     self.tree.OnItemAppend(self.tableau.parametres)
1270                 #get_table_param(self, self.filename)
1271                 #self.tableau.make_content()
1272                 #self.tableau.show_tab()
1273                 #open_data(self, self.filename)
1274             elif os.path.splitext(self.filename)[1] == '.txt':
1275                 self.OpenText()
1276             elif os.path.splitext(self.filename)[1] == '.ira' :
1277                 #self.corpus = Corpus(self)
1278                 #self.Text = OpenAnalyse(self, self.filename)
1279                 OpenAnalyse(self, self.filename)
1280         if not truepath:
1281             print('This file does not exist')
1282
1283
1284 #--------------------------------------------------------------------
1285 # contenu de l'ecran d'accueil
1286 # appelé seulement dans l'initialisation de IraFrame
1287 #--------------------------------------------------------------------
1288 class IntroPanel(wx.Panel):
1289     def __init__(self, parent):
1290         wx.Panel.__init__(self, parent)
1291         #col = randint(0, 255)
1292         #col1 = randint(0,255)
1293         #col2 = randint(0,255)
1294         #col = 57
1295         col = 161
1296         col1 = 198
1297         col2 = 224
1298         bckgrdcolor = wx.Colour(col, col1, col2)
1299         self.SetBackgroundColour(bckgrdcolor)
1300         txtcolour = wx.Colour(250, 250, 250)
1301         linkcolor = wx.Colour(255, 0, 0)
1302         sizer1 = wx.BoxSizer(wx.VERTICAL)
1303         sizer2 = wx.BoxSizer(wx.VERTICAL)
1304         sizer4 = wx.BoxSizer(wx.HORIZONTAL)
1305         grid_sizer_1 = wx.FlexGridSizer(1, 4, 0, 0)
1306         grid_sizer_3 = wx.FlexGridSizer(1, 4, 0, 0)
1307         grid_sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
1308         iralink = hl.HyperLinkCtrl(self,
1309             wx.ID_ANY,
1310             "http://www.iramuteq.org",
1311             URL="http://www.iramuteq.org")
1312         iralink.SetColours(linkcolor, linkcolor, "RED")
1313         iralink.SetBackgroundColour(bckgrdcolor)
1314         iralink.EnableRollover(True)
1315         iralink.SetUnderlines(False, False, True)
1316         iralink.SetBold(True)
1317         iralink.UpdateLink()
1318         PanelPres = wx.Panel(self)
1319         bckgrdcolor = wx.Colour(randint(0, 255), randint(0, 255), randint(0, 255))
1320         PanelPres.SetBackgroundColour(bckgrdcolor)
1321         label_1 = wx.StaticText(self, -1, "IRaMuTeQ", size=(-1, -1))
1322         label_1.SetFont(wx.Font(46,
1323             wx.FONTFAMILY_TELETYPE,
1324             wx.FONTSTYLE_NORMAL,
1325             wx.FONTWEIGHT_BOLD,
1326             0,
1327             "Purisa"))
1328         label_1.SetForegroundColour(wx.RED)
1329         iraicone = wx.Image(os.path.join(ImagePath,'iraicone100x100.png'), wx.BITMAP_TYPE_ANY).ConvertToBitmap()
1330         but_ira = wx.StaticBitmap(self, -1, bitmap = iraicone)
1331         label2 = wx.StaticText(PanelPres, -1 , '\nVersion ' + ConfigGlob.get('DEFAULT', 'version') + '\n')
1332         label2.SetForegroundColour(txtcolour)
1333         label2.SetBackgroundColour(bckgrdcolor)
1334         self.hyper2 = hl.HyperLinkCtrl(PanelPres, wx.ID_ANY, "REPERE", URL="http://repere.no-ip.org/")
1335         self.hyper2.SetColours(linkcolor, linkcolor, "RED")
1336         self.hyper2.SetBackgroundColour(bckgrdcolor)
1337         self.hyper2.EnableRollover(True)
1338         self.hyper2.SetUnderlines(False, False, True)
1339         self.hyper2.SetBold(True)
1340         self.hyper2.UpdateLink()
1341         label_lerass = wx.StaticText(PanelPres, -1, 'Laboratoire ')
1342         label_lerass.SetForegroundColour(txtcolour)
1343         label_lerass.SetBackgroundColour(bckgrdcolor)
1344         self.hyper_lerass = hl.HyperLinkCtrl(PanelPres, -1, 'LERASS', URL="http://www.lerass.com")
1345         self.hyper_lerass.SetColours(linkcolor, linkcolor, "RED")
1346         self.hyper_lerass.SetBackgroundColour(bckgrdcolor)
1347         self.hyper_lerass.EnableRollover(True)
1348         self.hyper_lerass.SetUnderlines(False, False, True)
1349         self.hyper_lerass.SetBold(True)
1350         self.hyper_lerass.UpdateLink()
1351         blank = wx.StaticText(PanelPres, -1, '\n')
1352         blank1 = wx.StaticText(PanelPres, -1, '\n')
1353         labellicence = wx.StaticText(PanelPres, -1, _("License GNU GPL"))
1354         labellicence.SetForegroundColour(txtcolour)
1355         labellicence.SetBackgroundColour(bckgrdcolor)
1356         labelcopy = wx.StaticText(PanelPres, -1, ConfigGlob.get('DEFAULT', 'copyright'))
1357         labelcopy.SetForegroundColour(txtcolour)
1358         labelcopy.SetBackgroundColour(bckgrdcolor)
1359         python_img = wx.Image(os.path.join(ImagePath,'python-logo.jpg'), wx.BITMAP_TYPE_ANY).ConvertToBitmap()
1360         r_img = wx.Image(os.path.join(ImagePath,'Rlogo.jpg'), wx.BITMAP_TYPE_ANY).ConvertToBitmap()
1361         lexique_img = wx.Image(os.path.join(ImagePath,'LexTexte4.jpg'), wx.BITMAP_TYPE_ANY).ConvertToBitmap()
1362         but_python = wx.BitmapButton(self, -1, python_img)
1363         but_lexique = wx.BitmapButton(self, -1, lexique_img)
1364         but_r = wx.BitmapButton(self, -1, r_img)
1365         self.Bind(wx.EVT_BUTTON, self.OnPython, but_python)
1366         self.Bind(wx.EVT_BUTTON, self.OnLexique, but_lexique)
1367         self.Bind(wx.EVT_BUTTON, self.OnR, but_r)
1368         grid_sizer_1.Add(self.hyper2, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 0)
1369         grid_sizer_3.Add(label_lerass, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 0)
1370         grid_sizer_3.Add(self.hyper_lerass, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL, 0)
1371         sizer4.Add(label_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5)
1372         sizer2.Add(label2, 0, wx.ALIGN_CENTER, 5)
1373         sizer2.Add(wx.StaticText(PanelPres, -1, ''), 0, wx.ALIGN_CENTER, 5)
1374         sizer2.Add(wx.StaticText(PanelPres, -1, ''), 0, wx.ALIGN_CENTER, 5)
1375         sizer2.Add(grid_sizer_3, 0, wx.ALIGN_CENTER, 5)
1376         sizer2.Add(wx.StaticText(PanelPres, -1, ' '), 0, wx.ALIGN_CENTER, 5)
1377         sizer2.Add(grid_sizer_1, 0, wx.ALIGN_CENTER, 5)
1378         sizer2.Add(labellicence, 0, wx.ALIGN_CENTER, 5)
1379         sizer2.Add(labelcopy, 0, wx.ALIGN_CENTER, 5)
1380         sizer1.Add(sizer4, 2, wx.ALIGN_CENTER_HORIZONTAL, 0)
1381         sizer1.Add(but_ira, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5)
1382         sizer1.Add(iralink, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_TOP, 5)
1383         sizer2.Add(wx.StaticText(PanelPres, -1, ''), 0, wx.ALIGN_CENTER, 10)
1384         PanelPres.SetSizer(sizer2)
1385         grid_sizer_2.Add(but_python, 1, wx.ALIGN_BOTTOM)
1386         grid_sizer_2.Add(but_lexique, 1, wx.ALIGN_BOTTOM)
1387         grid_sizer_2.Add(but_r, 1,  wx.ALIGN_BOTTOM)
1388         sizer1.Add(PanelPres, 0, wx.EXPAND |wx.ALL, 10)
1389         sizer1.Add(grid_sizer_2, 2, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 1)
1390         self.SetSizer(sizer1)
1391         sizer1.Fit(self)
1392
1393     def OnPython(self,evt):
1394         webbrowser.open('http://www.python.org')
1395
1396     def OnLexique(self,evt):
1397         webbrowser.open('http://www.lexique.org')
1398
1399     def OnR(self,evt):
1400         webbrowser.open('http://www.r-project.org')
1401
1402
1403 #--------------------------------------------------------------------
1404 # ecran d'accueil
1405 # appelé seulement par MyApp
1406 #--------------------------------------------------------------------
1407 class MySplashScreen(wx.adv.SplashScreen):
1408
1409     def __init__(self):
1410         bmp = wx.Image(os.path.join(ImagePath, 'splash.png')).ConvertToBitmap()
1411         wx.adv.SplashScreen.__init__(self, bmp,
1412             wx.adv.SPLASH_CENTRE_ON_SCREEN |
1413             wx.adv.SPLASH_TIMEOUT,
1414             1000,
1415             None,
1416             -1)
1417         self.Bind(wx.EVT_CLOSE, self.OnClose)
1418         self.fc = wx.CallLater(1, self.ShowMain)
1419
1420     def OnClose(self, evt):
1421         evt.Skip()
1422         self.Hide()
1423         if self.fc.IsRunning():
1424             self.fc.Stop()
1425             self.ShowMain()
1426
1427     def ShowMain(self):
1428         displaySize = wx.DisplaySize()
1429         w = displaySize[0]/1.2
1430         h = displaySize[1]/1.2
1431         frame = IraFrame(None, -1, "IRaMuTeQ " + ConfigGlob.get('DEFAULT', 'version'), size=(int(w), int(h)))
1432         frame.Show()
1433         frame.finish_init()
1434         frame.Upgrade()
1435         frame.OnOpenFromCmdl()
1436         #if self.fc.IsRunning():
1437         #    self.Raise()
1438         #wx.CallAfter(frame.ShowTip)
1439
1440
1441 class MyApp(wx.App):
1442
1443     def OnInit(self):
1444         """
1445         Create and show the splash screen.  It will then create and show
1446         the main frame when it is time to do so.
1447         """
1448         wx.SystemOptions.SetOption("mac.window-plain-transition", 1)
1449         self.SetAppName("Iramuteq")
1450         splash = MySplashScreen()
1451         splash.Show()
1452         return True
1453
1454 def main():
1455     app = MyApp(False)
1456     app.MainLoop()
1457
1458 if __name__ == '__main__':
1459     __name__ = 'Main'
1460     main()