Attention une mise à jour du service Gitlab va être effectuée le mardi 18 janvier (et non lundi 17 comme annoncé précédemment) entre 18h00 et 18h30. Cette mise à jour va générer une interruption du service dont nous ne maîtrisons pas complètement la durée mais qui ne devrait pas excéder quelques minutes.

charter.py 30 KB
Newer Older
VIGNET Pierre's avatar
VIGNET Pierre committed
1
2
3
## Filename    : charter.py
## Author(s)   : Geoffroy Andrieux
## Created     : 03/2010
4
5
## Revision    :
## Source      :
VIGNET Pierre's avatar
VIGNET Pierre committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
##
## Copyright 2010 : IRISA/IRSET
##
## This library is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published
## by the Free Software Foundation; either version 2.1 of the License, or
## any later version.
##
## This library is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF
## MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  The software and
## documentation provided here under is on an "as is" basis, and IRISA has
## no obligations to provide maintenance, support, updates, enhancements
## or modifications.
## In no event shall IRISA be liable to any party for direct, indirect,
## special, incidental or consequential damages, including lost profits,
## arising out of the use of this software and its documentation, even if
## IRISA have been advised of the possibility of such damage.  See
## the GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this library; if not, write to the Free Software Foundation,
## Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## The original code contained here was initially developed by:
##
##     Geoffroy Andrieux.
##     IRISA/IRSET
##     Symbiose team
##     IRISA  Campus de Beaulieu
36
37
##     35042 RENNES Cedex, FRANCE
##
VIGNET Pierre's avatar
VIGNET Pierre committed
38
39
40
41
42
43
44
45
46
47
48
49
##
## Contributor(s): Michel Le Borgne, Nolwenn Le Meur
##
"""
Main class for Cadbiom gui
"""

import gtk
import webbrowser

from gtk.gdk import screen_height, screen_width, color_parse, \
                  COLORSPACE_RGB, colormap_get_system, Pixbuf
50
from cadbiom.antlr3 import ANTLRFileStream, CommonTokenStream
VIGNET Pierre's avatar
VIGNET Pierre committed
51
52
53
54
55
56
57
58
59
60
61
62
63
64

from charter_info import CharterInfo
from edit_mvc import EditMVC
from utils.warn import  confirm, DialogEntry, cancel_warn
from utils.notebookUtils import create_custom_tab
from utils.text_page import BioSignalEditor
from utils.reporter import CompilReporter
from utils.fileHandling import FileChooser

from chart_controler import ChartClipboard
from chart_simulator.chart_simul_controler import \
                     ChartSimulControler, DisplayError
from chart_checker.chart_checker_controler  import ChartChecker
from chart_misc_widgets import SearchManager, SearchFrontier, \
65
                      LegendWindow, ImportPIDParam, ImportBioPAXParams
66
67
from cadbiom_gui.gt_gui.chart_static.chart_stat_controler import \
    STATWindow, SCCWindow, BAGWindow, DependencyGraphWindow
VIGNET Pierre's avatar
VIGNET Pierre committed
68

69
70
71
from cadbiom.models.guard_transitions.chart_model import ChartModel
from cadbiom.models.guard_transitions.translators.chart_lang import LangVisitor
from cadbiom.models.guard_transitions.translators.chart_xml import \
VIGNET Pierre's avatar
VIGNET Pierre committed
72
73
                  XmlVisitor, MakeModelFromXmlFile, \
                  MakeModelFromXmlString, XmlException
74
75
from cadbiom.models.guard_transitions.translators.cadlangLexer import cadlangLexer
from cadbiom.models.guard_transitions.translators.cadlangParser import cadlangParser
VIGNET Pierre's avatar
VIGNET Pierre committed
76

77
78
79
80
# Custom imports
from cadbiom.models.guard_transitions.analyser.static_analysis \
    import StaticAnalyzer

VIGNET Pierre's avatar
VIGNET Pierre committed
81
82
from layout import LayoutVisitor

83
import pkg_resources
VIGNET Pierre's avatar
VIGNET Pierre committed
84
85
86
87
88
89
90
91
92
93

class Charter(object):
    """
    charter main class
    """
    BG_COLOR = '#edf5ff'
    def __init__(self, cad):
        self.ident = "charter"
        self.cad_manager = cad

94
95
96
        # Gestion of the destroy of all subwindows opened from this one
        self.subwindows = set()

VIGNET Pierre's avatar
VIGNET Pierre committed
97
98
99
        # simul options
        self.simul_strict = True
        self.sim_flat_graph = False
100

VIGNET Pierre's avatar
VIGNET Pierre committed
101
102
103
104
        # common clipboard
        self.clipboard = ChartClipboard()
        # gui
        # Set the Glade file
105
106
107
108
109
        template = pkg_resources.resource_filename(
            __name__,
            "chart_glade/charter.glade"
        )
        self.wtree = gtk.glade.XML(template)
VIGNET Pierre's avatar
VIGNET Pierre committed
110
111
112
113
114
115
116
117
118
119
120
        # Get the Main Window, and connect the "destroy" event
        self.main_window = self.wtree.get_widget("TopModel")
        if (self.main_window):
            self.main_window.connect("delete_event", self.on_destroy)
        h_scr = screen_height()
        w_scr = screen_width()
        self.h_scr = int(h_scr)
        self.w_scr = int(w_scr)
        self.main_window.resize(int(w_scr * 0.9), int(h_scr * 0.9))
        color = color_parse(Charter.BG_COLOR)
        self.main_window.modify_bg(gtk.STATE_NORMAL, color)
121
        self.constraint_window = None
122
123
124
125
126

        # Accelerators
        self.my_accelerators = gtk.AccelGroup()
        self.main_window.add_accel_group(self.my_accelerators)

VIGNET Pierre's avatar
VIGNET Pierre committed
127
128
        # menu bar
        menu_bar = self.wtree.get_widget("menubar1")
129
        menu_bar.set_size_request(0, 25)
VIGNET Pierre's avatar
VIGNET Pierre committed
130
131
132
133
134
135
        menu_bar.modify_bg(gtk.STATE_NORMAL, color)

        menu_item =  self.wtree.get_widget("doc_menu")
        menu_item.connect("activate", self.show_doc)
        menu_item =  self.wtree.get_widget("legend_menu")
        menu_item.connect("activate", self.show_legend)
136

VIGNET Pierre's avatar
VIGNET Pierre committed
137
        menu_item =  self.wtree.get_widget("New_model")
138
        self.add_accelerator(menu_item, "<Control>n")
VIGNET Pierre's avatar
VIGNET Pierre committed
139
140
        menu_item.connect("activate", self.new_charts)
        menu_item =  self.wtree.get_widget("Import_cadbiom")
141
        self.add_accelerator(menu_item, "<Control>o")
VIGNET Pierre's avatar
VIGNET Pierre committed
142
        menu_item.connect("activate", self.choose_xml_file)
143
        menu_item =  self.wtree.get_widget("Import_BioPAX")
144
        self.add_accelerator(menu_item, "<Control>b")
145
        menu_item.connect("activate", self.choose_BioPAX_file)
VIGNET Pierre's avatar
VIGNET Pierre committed
146
147
148
149
150
        menu_item =  self.wtree.get_widget("Import_PID")
        menu_item.connect("activate", self.choose_pid_file)
        menu_item =  self.wtree.get_widget("Import_CadLang")
        menu_item.connect("activate", self.choose_cadlang_file)
        menu_item =  self.wtree.get_widget("Export_cadbiom")
151
        self.add_accelerator(menu_item, "<Control>s")
VIGNET Pierre's avatar
VIGNET Pierre committed
152
153
154
155
156
157
158
159
160
161
162
163
        menu_item.connect("activate", self.export_to_xml)
        menu_item =  self.wtree.get_widget("Export_cadlang")
        menu_item.connect("activate", self.export_to_lang)
        menu_item =  self.wtree.get_widget("Export_picture")
        menu_item.connect("activate", self.export_picture)
        menu_item =  self.wtree.get_widget("Hierarchical_TB")
        menu_item.connect("activate", self.do_layout, "hierarchical_TB")
        menu_item =  self.wtree.get_widget("Hierarchical_LR")
        menu_item.connect("activate", self.do_layout, "hierarchical_LR")
        menu_item =  self.wtree.get_widget("neato")
        menu_item.connect("activate", self.do_layout, "neato")
        menu_item =  self.wtree.get_widget("fdp")
164
        menu_item.connect("activate", self.do_layout, "fdp")
VIGNET Pierre's avatar
VIGNET Pierre committed
165
        menu_item =  self.wtree.get_widget("twopi")
166
        menu_item.connect("activate", self.do_layout, "twopi")
VIGNET Pierre's avatar
VIGNET Pierre committed
167
        menu_item =  self.wtree.get_widget("circo")
168
169
        menu_item.connect("activate", self.do_layout, "circo")

170
171
172
173
174
175
176
177
        menu_item =  self.wtree.get_widget("model_infos")
        menu_item.connect("activate", self.on_stats_info)
        menu_item =  self.wtree.get_widget("scc_search")
        menu_item.connect("activate", self.on_frontier_scc)
        menu_item =  self.wtree.get_widget("basal_activated_genes")
        menu_item.connect("activate", self.on_basal_activated_genes)
        menu_item =  self.wtree.get_widget("dependance_graph")
        menu_item.connect("activate", self.on_dependency_graph)
VIGNET Pierre's avatar
VIGNET Pierre committed
178
179
180

        # Model Handling buttons
        button = self.wtree.get_widget("Check_button")
181
182
        button.set_label(button.get_label() + " (F8)")
        self.add_accelerator(button, "F8")
183
184
        button.connect("clicked", self.check)

185
186
187
188
189
        button = self.wtree.get_widget("Simu_button")
        button.set_label(button.get_label() + " (F9)")
        self.add_accelerator(button, "F9")
        button.connect("clicked", self.on_simulate)

VIGNET Pierre's avatar
VIGNET Pierre committed
190
191
        # graph drawing controler buttons (not connected)
        self.graph_notebook = self.wtree.get_widget("graph_notebook")
192
        self.graph_notebook.connect("switch-page",
VIGNET Pierre's avatar
VIGNET Pierre committed
193
194
195
196
197
198
199
                                    self.switch_graph_page_callback)
        self.create_drawing_buttons()

        # edit MVC
        self.ei_id = 0
        self.edit_mvc_list = []
        self.current_edit_mvc = None
200

VIGNET Pierre's avatar
VIGNET Pierre committed
201
202
203
204
205
206
207
208
        # chart info
        chart_info_frame = self.wtree.get_widget("informations_frame")
        self.chart_info = CharterInfo(chart_info_frame)
        self.chart_info.trans_info.show.connect("clicked", self.display_states)
        mtk_notebook = self.wtree.get_widget("MTK_notebook")
        # search
        self.search_area = SearchManager(self, mtk_notebook, "Simple node list")
        self.search_frontier = SearchFrontier(self, mtk_notebook, "Frontier")
209

VIGNET Pierre's avatar
VIGNET Pierre committed
210
211
212
213
214
215
216
217
218
        # overview
        self.overview_window = self.wtree.get_widget("Overview")


    def refresh(self):
        """
        TODO
        """
        pass
219

VIGNET Pierre's avatar
VIGNET Pierre committed
220
221
222
223
224
    def hide(self):
        """
        Useful ?
        """
        self.main_window.hide_all()
225

VIGNET Pierre's avatar
VIGNET Pierre committed
226
227
    def create_drawing_buttons(self):
        """
228
        create the buttons to control drawing
VIGNET Pierre's avatar
VIGNET Pierre committed
229
230
231
        """
        self.button_handlers = dict()
        c_box = self.wtree.get_widget("controler_box")
232

VIGNET Pierre's avatar
VIGNET Pierre committed
233
        but = gtk.Button(label="Select")
VIGNET Pierre's avatar
VIGNET Pierre committed
234
235
        c_box.add(but)
        self.button_handlers["Select"] = (but, -1)
236

VIGNET Pierre's avatar
VIGNET Pierre committed
237
        but = gtk.Button(label="InputNode (F1)")
238
        self.add_accelerator(but, "F1")
VIGNET Pierre's avatar
VIGNET Pierre committed
239
240
        c_box.add(but)
        self.button_handlers["InputNode"] = (but, -1)
241

VIGNET Pierre's avatar
VIGNET Pierre committed
242
        but = gtk.Button(label="SimpleNode (F2)")
243
        self.add_accelerator(but, "F2")
VIGNET Pierre's avatar
VIGNET Pierre committed
244
245
        c_box.add(but)
        self.button_handlers["SimpleNode"] = (but, -1)
246

VIGNET Pierre's avatar
VIGNET Pierre committed
247
        but = gtk.Button(label="PermNode (F3)")
248
        self.add_accelerator(but, "F3")
VIGNET Pierre's avatar
VIGNET Pierre committed
249
250
        c_box.add(but)
        self.button_handlers["PermNode"] = (but, -1)
251

VIGNET Pierre's avatar
VIGNET Pierre committed
252
        but = gtk.Button(label="StartNode (F4)")
253
        self.add_accelerator(but, "F4")
VIGNET Pierre's avatar
VIGNET Pierre committed
254
255
        c_box.add(but)
        self.button_handlers["StartNode"] = (but, -1)
256

VIGNET Pierre's avatar
VIGNET Pierre committed
257
        but = gtk.Button(label="TrapNode (F5)")
258
        self.add_accelerator(but, "F5")
VIGNET Pierre's avatar
VIGNET Pierre committed
259
260
        c_box.add(but)
        self.button_handlers["TrapNode"] = (but, -1)
261

VIGNET Pierre's avatar
VIGNET Pierre committed
262
        but = gtk.Button(label="Transition (F6)")
263
        self.add_accelerator(but, "F6")
VIGNET Pierre's avatar
VIGNET Pierre committed
264
265
        c_box.add(but)
        self.button_handlers["Transition"] = (but, -1)
266

VIGNET Pierre's avatar
VIGNET Pierre committed
267
        but = gtk.Button(label="Constraints (F7)")
268
        self.add_accelerator(but, "F7")
VIGNET Pierre's avatar
VIGNET Pierre committed
269
270
        c_box.add(but)
        self.button_handlers["Constraints"] = (but, -1)
271

VIGNET Pierre's avatar
VIGNET Pierre committed
272
273
274
275
276
        # zoom
        but = self.wtree.get_widget("zoomp")
        self.button_handlers["zoom_p"] = (but, -1)
        but = self.wtree.get_widget("zoomm")
        self.button_handlers["zoom_m"] = (but, -1)
277
278


VIGNET Pierre's avatar
VIGNET Pierre committed
279
280
281
282
283
284
    def drawing_button_connect(self):
        """
        Connect the buttons to the controler of the graphic view
        Remember for each button the handler
        """
        (but, bhan) = self.button_handlers["Select"]
285
        bhan = but.connect("clicked",
VIGNET Pierre's avatar
VIGNET Pierre committed
286
287
                         self.current_edit_mvc.controler.set_action_select)
        self.button_handlers["Select"] = (but, bhan)
288

VIGNET Pierre's avatar
VIGNET Pierre committed
289
        (but, bhan) = self.button_handlers["InputNode"]
290
        bhan = but.connect("clicked",
VIGNET Pierre's avatar
VIGNET Pierre committed
291
292
                    self.current_edit_mvc.controler.set_action_new_input_node)
        self.button_handlers["InputNode"] = (but, bhan)
293

VIGNET Pierre's avatar
VIGNET Pierre committed
294
        (but, bhan) = self.button_handlers["SimpleNode"]
295
        bhan = but.connect("clicked",
VIGNET Pierre's avatar
VIGNET Pierre committed
296
297
                    self.current_edit_mvc.controler.set_action_new_simple_node)
        self.button_handlers["SimpleNode"] = (but, bhan)
298

VIGNET Pierre's avatar
VIGNET Pierre committed
299
        (but, bhan) = self.button_handlers["PermNode"]
300
        bhan = but.connect("clicked",
VIGNET Pierre's avatar
VIGNET Pierre committed
301
302
                    self.current_edit_mvc.controler.set_action_new_perm_node)
        self.button_handlers["PermNode"] = (but, bhan)
303
304


VIGNET Pierre's avatar
VIGNET Pierre committed
305
        (but, bhan) = self.button_handlers["StartNode"]
306
        bhan = but.connect("clicked",
VIGNET Pierre's avatar
VIGNET Pierre committed
307
308
                    self.current_edit_mvc.controler.set_action_new_start_node)
        self.button_handlers["StartNode"] = (but, bhan)
309

VIGNET Pierre's avatar
VIGNET Pierre committed
310
        (but, bhan) = self.button_handlers["TrapNode"]
311
        bhan = but.connect("clicked",
VIGNET Pierre's avatar
VIGNET Pierre committed
312
313
                    self.current_edit_mvc.controler.set_action_new_trap_node)
        self.button_handlers["TrapNode"] = (but, bhan)
314

VIGNET Pierre's avatar
VIGNET Pierre committed
315
        (but, bhan) = self.button_handlers["Transition"]
316
        bhan = but.connect("clicked",
VIGNET Pierre's avatar
VIGNET Pierre committed
317
318
                    self.current_edit_mvc.controler.set_action_new_transition)
        self.button_handlers["Transition"] = (but, bhan)
319

VIGNET Pierre's avatar
VIGNET Pierre committed
320
321
322
        (but, bhan) = self.button_handlers["Constraints"]
        bhan = but.connect("clicked", self.edit_constraints)
        self.button_handlers["Constraints"] = (but, bhan)
323

VIGNET Pierre's avatar
VIGNET Pierre committed
324
325
326
        (but, bhan) = self.button_handlers["zoom_p"]
        bhan = but.connect("clicked", self.current_edit_mvc.zoom_plus)
        self.button_handlers["zoom_p"] = (but, bhan)
327

VIGNET Pierre's avatar
VIGNET Pierre committed
328
329
        (but, bhan) = self.button_handlers["zoom_m"]
        bhan = but.connect("clicked", self.current_edit_mvc.zoom_minus)
330
331
        self.button_handlers["zoom_m"] = (but, bhan)

332
333
334
335
336
337
338
339
340
341
342
343
344
345
    def add_accelerator(self, widget, accelerator, signal="activate"):
        """Adds a keyboard shortcut"""
        if accelerator is not None:
            #if DEBUG:
                #print accelerator, widget.get_tooltip_text()
            key, mod = gtk.accelerator_parse(accelerator)
            # VISIBLE: if set, the accelerator is visible in a label
            widget.add_accelerator(signal,
                                   self.my_accelerators,
                                   key, mod,
                                   gtk.ACCEL_VISIBLE,
            )
            # print "The accelerator is well added with the signal " + signal

VIGNET Pierre's avatar
VIGNET Pierre committed
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
    def drawing_button_disconnect(self):
        """
        Disconnect graphic editor buttons
        Carefull: do not change value of handler for efficiency reason
        """
        for k in self.button_handlers.keys():
            bhan = self.button_handlers[k]
            bhan[0].disconnect(bhan[1])

    def drawing_button_disable(self):
        """
        Disconnect graphic editor buttons
        Carefull: do not change value of handler for efficiency reason
        """
        for k in self.button_handlers.keys():
            bhan = self.button_handlers[k]
            bhan[0].set_sensitive(False)

    def drawing_button_unable(self):
        """
        Disconnect graphic editor buttons
        Carefull: do not change value of handler for efficiency reason
        """
        for k in self.button_handlers.keys():
            bhan = self.button_handlers[k]
            bhan[0].set_sensitive(True)
372

373
    def on_destroy(self, widget, _dummy_event):
VIGNET Pierre's avatar
VIGNET Pierre committed
374
375
376
377
378
379
380
381
382
383
384
385
386
        """
        destroy if everything OK
        """
        # check if some models are modified
        for emvc in self.edit_mvc_list:
            if emvc.model.is_modified():
                name = emvc.model.name
                ask = False
                ask = confirm(None, 'Model '+name+' is modified - Quit anyway?')
                if not ask:
                    return True
            emvc.clean_subwin()
        gtk.main_quit()
387

VIGNET Pierre's avatar
VIGNET Pierre committed
388
389
390
391
392
    def show(self):
        """
        TODO check if useful
        """
        self.main_window.show_all()
393
394


VIGNET Pierre's avatar
VIGNET Pierre committed
395
396
397
398
399
    def delete_tab_callback(self, widget):
        """
        Delete current edit_MVC and corresponding view
        """
        self.remove_edit_mvc()
400
401


VIGNET Pierre's avatar
VIGNET Pierre committed
402

VIGNET Pierre's avatar
VIGNET Pierre committed
403
    def add_edit_mvc(self, model_name, model=None, layout=False):
VIGNET Pierre's avatar
VIGNET Pierre committed
404
        """
405
        create, register and display a new edit_mvc - close all windows
VIGNET Pierre's avatar
VIGNET Pierre committed
406
407
        associated with a previous edit_mvc
        """
408

VIGNET Pierre's avatar
VIGNET Pierre committed
409
410
411
412
413
        # edit MVC
        edm = EditMVC(self, model_name, model, layout)
        (eventbox, button) = create_custom_tab(edm.title)
        button.connect("clicked", self.delete_tab_callback)
        edm.tab_button = button
414

VIGNET Pierre's avatar
VIGNET Pierre committed
415
416
417
418
419
        # insert in emvc management
        page_index = self.graph_notebook.append_page(edm.viewpage, eventbox)
        self.edit_mvc_list.append(edm)
        self.set_current_edit_mvc(edm)
        self.graph_notebook.set_current_page(page_index)
420

VIGNET Pierre's avatar
VIGNET Pierre committed
421
    def add_display_mvc(self, model_name, model=None, layout=False):
VIGNET Pierre's avatar
VIGNET Pierre committed
422
423
424
425
426
427
428
429
        """
        create, register and display a new edit_mvc
        """
        # edit MVC
        edm = EditMVC(self, model_name, model, layout)
        (eventbox, button) = create_custom_tab(edm.title)
        button.connect("clicked", self.delete_tab_callback)
        edm.tab_button = button
430

VIGNET Pierre's avatar
VIGNET Pierre committed
431
432
433
        # insert in emvc management
        page_index = self.graph_notebook.append_page(edm.viewpage, eventbox)
        self.edit_mvc_list.append(edm)
VIGNET Pierre's avatar
VIGNET Pierre committed
434
        self.set_current_edit_mvc(edm, False) # do not destroy aux windows
VIGNET Pierre's avatar
VIGNET Pierre committed
435
        self.graph_notebook.set_current_page(page_index)
436
437


VIGNET Pierre's avatar
VIGNET Pierre committed
438
439
440
441
442
443
    def remove_edit_mvc(self):
        """
        Remove current edit_MVC
        """
        if not self.current_edit_mvc:
            return
444
        eimvc = self.current_edit_mvc
VIGNET Pierre's avatar
VIGNET Pierre committed
445
446
447
448
449
450
451
452
453
454
455
        # modified model??
        ask = True
        if not eimvc.model.is_submodel():
            if eimvc.model.is_modified():
                ask = confirm(None, "Modified model. Do you want to delete?")
        if ask:
            # remove from notebook and navigator
            self.search_area.clear()
            self.search_frontier.clear()
            self.overview_window.get_child().get_child().clear()
            # following implies a switch page (thus disconnection)
456
            self.graph_notebook.remove(eimvc.viewpage)
VIGNET Pierre's avatar
VIGNET Pierre committed
457
458
459
            # remove from list
            self.edit_mvc_list.remove(eimvc)
            eimvc.clean_subwin()
460

VIGNET Pierre's avatar
VIGNET Pierre committed
461
462
463
464
465
466
467
468
469
    def open_macro(self, mnode):
        """
        open a macro state in an other tab
        """
        edm = EditMVC(self, mnode.name)
        edm.model.make_submodel(mnode)
        edm.model.get_root()
        # attach submodel view to whole model
        mnode.model.attach(edm.view)
470

VIGNET Pierre's avatar
VIGNET Pierre committed
471
472
473
474
        (eventbox, button) = create_custom_tab(edm.title)
        button.connect("clicked", self.delete_tab_callback)
        edm.tab_button = button
        page_index = self.graph_notebook.append_page(edm.viewpage, eventbox)
475
        self.edit_mvc_list.append(edm)
VIGNET Pierre's avatar
VIGNET Pierre committed
476
477
        self.set_current_edit_mvc(edm)
        edm.view.show()
478
479
        self.graph_notebook.set_current_page(page_index)

VIGNET Pierre's avatar
VIGNET Pierre committed
480
481
482
483
484
485
486
487
    def set_current_edit_mvc(self, edm, w_destroy=True):
        """
        display a new current edit item
        """
        # disconnect the currrent one if any
        if self.current_edit_mvc:
            self.save_constraints(None)
            self.current_edit_mvc.disconnect(self, w_destroy)
488

VIGNET Pierre's avatar
VIGNET Pierre committed
489
490
491
492
493
494
        if edm:
            self.current_edit_mvc = edm
            edm.connect(self)
            # refresh search
            self.search_area.set_model(edm.model)
            self.search_frontier.set_model(edm.model)
495

VIGNET Pierre's avatar
VIGNET Pierre committed
496
497
498
499
500
501
502
503
    def get_emvc_with_view(self, view):
        """
        Retreive the edit_MVC from the view
        """
        for emvc in self.edit_mvc_list:
            if emvc.view == view:
                return emvc
        return None
504

VIGNET Pierre's avatar
VIGNET Pierre committed
505
506
507
508
509
510
511
512
513
514
515
    def switch_graph_page_callback(self, widget, page, page_index):
        """
        Standard notebook call back
        """
        if page_index >= 0:
            the_view = self.graph_notebook.get_nth_page(page_index).draw
            edm = self.get_emvc_with_view(the_view)
            if edm: # for the first case
                self.set_current_edit_mvc(edm)
        else: # no more page (in case of delete)
            pass
516

VIGNET Pierre's avatar
VIGNET Pierre committed
517
518
519
520
521
522
523
524
525
526
527
528
529
    def ok_new_text(self, but, dialog):
        """
        Prompt if new model - to give the name
        """
        model_name = dialog.entry.get_text()
        dialog.destroy()
        self.add_edit_mvc(model_name)

    def cancel(self, but, dee):
        """
        what?
        """
        dee.destroy()
530
531


VIGNET Pierre's avatar
VIGNET Pierre committed
532
533
534
535
536
    def new_charts(self, widget):
        """
        create a new charts when you click on new
        """
        # open an independant gtk.Entry for asking for the name
537
        die = DialogEntry("Insert a model name")
VIGNET Pierre's avatar
VIGNET Pierre committed
538
539
540
        die.okb.connect("clicked", self.ok_new_text, die)
        die.cancel.connect("clicked", self.cancel, die)
        die.run()
541

VIGNET Pierre's avatar
VIGNET Pierre committed
542
543
544
545
546
547
548
549
550
551
552
553
554
555

    def save_choice(self):
        """
        choice of file for save
        """
        dialog = gtk.Dialog("",
                            None,
                            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                            ("Yes", 0, "No", 1, "Cancel", 2))
        label = gtk.Label("Do yous want to delete previous xml model?")
        dialog.vbox.pack_start(label, True, False, 0)
        label.show()
        response = dialog.run()
        dialog.destroy()
556
557
        return response

VIGNET Pierre's avatar
VIGNET Pierre committed
558
559
560
561
562
563
564
    def export_to_xml(self, widget):
        """
        open a window to save as xml file
        """
        fch = FileChooser("Export to xml", "bcx files", "*.bcx")
        fch.do_action(self.create_xml_file)

565

VIGNET Pierre's avatar
VIGNET Pierre committed
566
567
568
569
570
571
572
573
574
575
    def create_xml_file(self, xml_file):
        """
        make a xml file with the current model
        """
        if self.current_edit_mvc.model.is_submodel():
            model = self.current_edit_mvc.controler.current_node.model
        else :
            model = self.current_edit_mvc.model
        try:
            xml = XmlVisitor(model)
VIGNET Pierre's avatar
VIGNET Pierre committed
576
            mfile = open(xml_file, 'w')
577
            mfile.write(xml.return_xml())
VIGNET Pierre's avatar
VIGNET Pierre committed
578
            mfile.close()
VIGNET Pierre's avatar
VIGNET Pierre committed
579
        except XmlException as xec:
VIGNET Pierre's avatar
VIGNET Pierre committed
580
581
            cancel_warn(xec.message)
            return
582

VIGNET Pierre's avatar
VIGNET Pierre committed
583
584
585
586
    def choose_xml_file(self, widget):
        """
        open a window to search xml file
        """
587
        fch = FileChooser("Import Cadbiom model", "bcx files", "*.bcx")
VIGNET Pierre's avatar
VIGNET Pierre committed
588
        fch.do_action(self.import_from_xml_file)
589

VIGNET Pierre's avatar
VIGNET Pierre committed
590
591
592
593
594
    def import_from_xml_file(self, ffile):
        """
        As it says
        """
        self.import_from_xml(ffile, ffile=True)
595

VIGNET Pierre's avatar
VIGNET Pierre committed
596
597
598
599
600
601
602
603
604
605
606
607
608
    def import_from_xml(self, xml_cont, ffile=False):
        """
        open and parse an xml file or from db
        """
        if ffile:
            parsing = MakeModelFromXmlFile(xml_cont)
        else:
            parsing = MakeModelFromXmlString(xml_cont)
        # chart model
        model = parsing.get_model()
        model.modified = False
        self.add_edit_mvc(model.name, model)

609

VIGNET Pierre's avatar
VIGNET Pierre committed
610
611
612
613
    def choose_cadlang_file(self, widget):
        """
        open a window to search xml file
        """
614
        fch = FileChooser("Import from Cadbiom-chart lang",
VIGNET Pierre's avatar
VIGNET Pierre committed
615
616
                          "cadbiom-l", "*.cal")
        fch.do_action(self.import_from_cl_file)
617

VIGNET Pierre's avatar
VIGNET Pierre committed
618
619
620
621
622
623
    def import_from_cl_file(self, ffile):
        """
        As it says
        """
        crep = CompilReporter()
        fstream = ANTLRFileStream(ffile)
624
        lexer = cadlangLexer(fstream)
VIGNET Pierre's avatar
VIGNET Pierre committed
625
626
627
628
629
630
631
632
633
634
        lexer.set_error_reporter(crep)
        parser = cadlangParser(CommonTokenStream(lexer))
        parser.set_error_reporter(crep)
        model = ChartModel(ffile)
        parser.cad_model(model)
        if crep.error:
            DisplayError(crep, ffile)
            return
        model = parser.model
        self.add_edit_mvc(model.name, model, False)
VIGNET Pierre's avatar
VIGNET Pierre committed
635
        self.do_layout(None, "hierarchical_LR")
636

VIGNET Pierre's avatar
VIGNET Pierre committed
637
638
639
640
641

    def choose_pid_file(self, widget):
        """
        open a window to search xml file coming from PID database
        """
642
643
        # Pass the parent window to set modal mode on the child
        ImportPIDParam(self, self.main_window)
644
645
646
647
648

    def choose_BioPAX_file(self, widget):
        """
        open a window to import BioPAX data from a triplestore
        """
649
        # Pass the parent window to set modal mode on the child
650
        ImportBioPAXParams(self, self.main_window)
VIGNET Pierre's avatar
VIGNET Pierre committed
651
652
653

    def export_to_lang(self, widget):
        """
654
        Export to CadLang
VIGNET Pierre's avatar
VIGNET Pierre committed
655
656
657
        """
        fch = FileChooser("Export to Cadbiom-chart lang", "cadbiom-l", "*.cal")
        fch.do_action(self.compile_to_lang)
658

VIGNET Pierre's avatar
VIGNET Pierre committed
659
660
661
662
    def compile_to_lang(self, file_name):
        """
        Compile in view of exporting
        """
VIGNET Pierre's avatar
VIGNET Pierre committed
663
        out = open(file_name, "w")
VIGNET Pierre's avatar
VIGNET Pierre committed
664
665
666
667
668
669
670
671
672
        # decompiler visitor
        lvi = LangVisitor(out)
        edm = self.current_edit_mvc
        if edm:
            edm.model.accept(lvi)
            out.close()
        else:
            return

673

VIGNET Pierre's avatar
VIGNET Pierre committed
674
675
676
677
    def show_doc(self, widget):
        """
        Doc
        """
678
        url = 'http://cadbiom.genouest.org/cw_support.html'
VIGNET Pierre's avatar
VIGNET Pierre committed
679
680
        webbrowser.open(url)
        return
681

VIGNET Pierre's avatar
VIGNET Pierre committed
682
683
684
685
    def show_legend(self, widget):
        """
        Doc
        """
686
        self.legend = LegendWindow(self)
687

VIGNET Pierre's avatar
VIGNET Pierre committed
688
689
690
691
692
693
694
    def export_picture(self, widget):
        """
        Export a picture (png,jpg) of the current model
        """
        fch = FileChooser("Export picture", "pictures", "*.png")
        fch.get_filter().add_pattern("*.png")
        fch.do_action(self.export_picture_to_file)
695

VIGNET Pierre's avatar
VIGNET Pierre committed
696
697
698
699
700
701
702
703
    def export_picture_to_file(self, file_name):
        """
        As it says
        """
        if self.current_edit_mvc:
            edm = self.current_edit_mvc
        else:
            return
704

VIGNET Pierre's avatar
VIGNET Pierre committed
705
706
707
708
709
710
        fns = file_name.split('.')
        if len(fns)!= 2:
            cancel_warn("Incorrect picture file name" )
            return
        suff = fns[1]
        pxm = edm.view.pixmap
711
        pxb = Pixbuf(COLORSPACE_RGB, False, 8,
VIGNET Pierre's avatar
VIGNET Pierre committed
712
                    edm.view.draw_width, edm.view.draw_height)
VIGNET Pierre's avatar
VIGNET Pierre committed
713
        pxb.get_from_drawable(pxm, colormap_get_system(), 0, 0, 0, 0, -1, -1)
VIGNET Pierre's avatar
VIGNET Pierre committed
714
715
716
717
718
719
        if suff == 'png':
            pxb.save(file_name, 'png')
        elif suff == 'jpg':
            pxb.save(file_name, "jpeg", {"quality":"100"})
        else:
            cancel_warn("Unknown picture format")
720

VIGNET Pierre's avatar
VIGNET Pierre committed
721
722
723
724
725
726
727
728
729
730
731
    def do_layout(self, widget, layout_style):
        """
        Compute a layout of the model
        """
        if self.current_edit_mvc:
            edm = self.current_edit_mvc
        else:
            return
        lvi = LayoutVisitor(edm.view, layout_style)
        edm.model.accept(lvi)
        edm.display()
732

VIGNET Pierre's avatar
VIGNET Pierre committed
733
734
735
736
737
738
739
    # simulation
    def on_simulate(self, widget):
        """
        Call simulation
        """
        reporter = CompilReporter()
        if self.current_edit_mvc:
740
            chart_simul = ChartSimulControler(self.current_edit_mvc,
VIGNET Pierre's avatar
VIGNET Pierre committed
741
742
                                              True, reporter)

743

VIGNET Pierre's avatar
VIGNET Pierre committed
744
    # static analysis
745
746
747
748
749
750
751
752
753
#    def on_static(self, widget):
#        """
#        Call static analysis
#        """
#        if self.current_edit_mvc:
#            reporter = CompilReporter()
#            chart_static = ChartStatControler(self.current_edit_mvc, reporter)

    def on_stats_info(self, widget):
VIGNET Pierre's avatar
VIGNET Pierre committed
754
        """
755
        Fill window with model informations.
VIGNET Pierre's avatar
VIGNET Pierre committed
756
757
758
        """
        if self.current_edit_mvc:
            reporter = CompilReporter()
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
            # get stats from StaticAnalyzer
            stan = StaticAnalyzer(reporter)
            stan.build_from_chart_model(self.current_edit_mvc.model)
            ststat = stan.get_statistics()
            window = STATWindow(ststat, self.current_edit_mvc, reporter, self)
            # Get Main widget and connect its "destroy" event
            window.window.connect("destroy", self.win_remove)

    def on_frontier_scc(self, widget):
        """
        Compute connected components which are on the frontier
        """
        if self.current_edit_mvc:
            reporter = CompilReporter()
            stan = StaticAnalyzer(reporter)
            stan.build_from_chart_model(self.current_edit_mvc.model)
            # errors??
            lscc = stan.get_frontier_scc()
            window = SCCWindow(lscc, self.current_edit_mvc, reporter, self)
            # Get Main widget and connect its "destroy" event
            window.window.connect("destroy", self.win_remove)

    def on_basal_activated_genes(self, widget):
        """
        Compute basal activated genes
        """
        if self.current_edit_mvc:
            reporter = CompilReporter()
            stan = StaticAnalyzer(reporter)
            stan.build_from_chart_model(self.current_edit_mvc.model)
            lwbag = stan.get_why_basal_genes()
            window = BAGWindow(lwbag, self.current_edit_mvc, reporter, self)
            # Get Main widget and connect its "destroy" event
            window.window.connect("destroy", self.win_remove)

    def on_dependency_graph(self, widget):
        """
        Computation and export of the dependance graph
        """
        if self.current_edit_mvc:
            reporter = CompilReporter()
            StaticAnalyzer(reporter)
            DependencyGraphWindow(self.current_edit_mvc, reporter, self)

    def win_register(self, window):
        """Register a sub window
        This window will be destroyed when you connect its main widget
        event "destroy" to subwin_on_destroy()
        """
        self.subwindows.add(window)

    def win_remove(self, window):
        """Destroy a sub window
        This window will be destroyed when you connect its main widget
        event "destroy" to subwin_on_destroy()
        """
        self.subwindows.remove(window)
        window.destroy()
VIGNET Pierre's avatar
VIGNET Pierre committed
817
818
819
820
821
822
823
824
825

    # solve
    def check(self, widget):
        """
        Launch checker
        """
        if self.current_edit_mvc:
            reporter = CompilReporter()
            chart_check = ChartChecker(self.current_edit_mvc, reporter)
826

VIGNET Pierre's avatar
VIGNET Pierre committed
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

    def get_em_with_model_name(self, name):
        """
        get em in list of edit_MVC
        """
        for edm in self.edit_mvc_list:
            if edm.title == name:
                return edm
        return None

    def update(self, mnode):
        """
        observer method
        """
        if mnode.name != self.current_edit_mvc.title:
            list_model = []
            for edm in self.edit_mvc_list:
                list_model.append(edm.model.name)
            if mnode.name in list_model:
                pass
            else:
                self.open_macro(mnode)
849
        else :
VIGNET Pierre's avatar
VIGNET Pierre committed
850
            pass
851

VIGNET Pierre's avatar
VIGNET Pierre committed
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884

    def display_states(self, widget):
        """
        As it says
        """
        cst = self.chart_info.trans_info.trans.get_influencing_places()
        ndic = self.current_edit_mvc.model.simple_node_dict
        for ident in cst:
            try:
                ndic[ident].search_mark = True
            except:
                pass
        self.current_edit_mvc.view.update()

    def edit_constraints(self, widget):
        """
        Constraint editor
        """
        model = self.current_edit_mvc.model
        # what_to_do = save_constraints
        self.constraint_window =  BioSignalEditor('Constraints: '+model.name,
                                                   self, self.save_constraints)
        self.constraint_window.set_text(model.constraints)

    def save_constraints(self, edit):
        """
        For export
        """
        if self.constraint_window:
            model = self.current_edit_mvc.model
            model.constraints = edit.get_text()
            model.modified = True
            self.constraint_window = None
885