~vbkaisetsu/glogic/trunk

« back to all changes in this revision

Viewing changes to glogic/MainFrame.py

  • Committer: Koichi Akabe
  • Date: 2012-04-26 13:41:41 UTC
  • Revision ID: vbkaisetsu@gmail.com-20120426134141-mto9lyd7mfzkp4u3
initial commit (ported from wxlogic)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8; indent-tabs-mode: t; tab-width: 4 -*-
 
2
 
 
3
import copy, os, sys, webbrowser, gettext
 
4
from gi.repository import Gtk, Gdk, GdkPixbuf
 
5
from glogic import config, const
 
6
from gettext import gettext as _
 
7
from glogic.DrawArea import DrawArea
 
8
from glogic.ComponentWindow import ComponentWindow
 
9
from glogic.CircuitManager import CircuitManager
 
10
from glogic.PropertyWindow import PropertyWindow
 
11
from glogic.Components import *
 
12
from glogic.TimingChartWindow import TimingChartWindow
 
13
 
 
14
gettext.textdomain("glogic")
 
15
 
 
16
themed_icons = Gtk.IconTheme.get_default()
 
17
themed_icons.append_search_path(config.DATADIR+"/images")
 
18
 
 
19
class MainFrame(Gtk.Window):
 
20
        def __init__(self):
 
21
                Gtk.Window.__init__(self, title="%s - %s" % (const.text_notitle, const.app_name))
 
22
                
 
23
                self.running_mode = False
 
24
                
 
25
                self.circuit = CircuitManager(self)
 
26
                
 
27
                self.create_window()
 
28
                
 
29
                if len(sys.argv) >= 2:
 
30
                        self.circuit.open_file(sys.argv[1])
 
31
                        self.drawarea.redraw = True
 
32
                        self.drawarea.queue_draw()
 
33
        
 
34
        def create_window(self):
 
35
                self.set_default_size(640, 400)
 
36
                box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
 
37
                # Menu bar
 
38
                menu_xml = """
 
39
                <ui>
 
40
                        <menubar name="MenuBar">
 
41
                                <menu action="file">
 
42
                                        <menuitem action="new"/>
 
43
                                        <menuitem action="open"/>
 
44
                                        <separator/>
 
45
                                        <menuitem action="save"/>
 
46
                                        <menuitem action="saveas"/>
 
47
                                        <separator/>
 
48
                                        <menuitem action="quit"/>
 
49
                                </menu>
 
50
                                <menu action="edit">
 
51
                                        <menuitem action="undo"/>
 
52
                                        <menuitem action="redo"/>
 
53
                                        <separator/>
 
54
                                        <!--
 
55
                                        <menuitem action="cut"/>
 
56
                                        <menuitem action="copy"/>
 
57
                                        <menuitem action="paste"/>
 
58
                                        <separator/> 
 
59
                                        -->
 
60
                                        <menuitem action="delete"/>
 
61
                                        <separator/>
 
62
                                        <menuitem action="property"/>
 
63
                                </menu>
 
64
                                <menu action="add">
 
65
                                        <menuitem action="components"/>
 
66
                                        <menuitem action="net"/>
 
67
                                </menu>
 
68
                                <menu action="simulate">
 
69
                                        <menuitem action="run"/>
 
70
                                        <menuitem action="chart"/>
 
71
                                </menu>
 
72
                                <menu action="help">
 
73
                                        <menuitem action="trans"/>
 
74
                                        <menuitem action="report"/>
 
75
                                        <separator/>
 
76
                                        <menuitem action="about"/>
 
77
                                </menu>
 
78
                        </menubar>
 
79
                        <toolbar name='ToolBar'>
 
80
                                <toolitem action='new' />
 
81
                                <toolitem action='open' />
 
82
                                <toolitem action='save' />
 
83
                                <separator/>
 
84
                                <toolitem action='undo' />
 
85
                                <toolitem action='redo' />
 
86
                                <separator/>
 
87
                                <toolitem action='components' />
 
88
                                <toolitem action='net' />
 
89
                                <separator/>
 
90
                                <toolitem action='run' />
 
91
                        </toolbar>
 
92
                </ui>
 
93
                """
 
94
                
 
95
                actiongroup = Gtk.ActionGroup("menu")
 
96
                actions = [
 
97
                        ("new",       Gtk.STOCK_NEW, _("_New"), "<Control>N", _("Close this circuit and create a new one."), self.on_action_new_pressed),
 
98
                        ("open",      Gtk.STOCK_OPEN, _("_Open..."), "<Control>O", _("Close this circuit and open the other one."), self.on_action_open_pressed),
 
99
                        ("save",      Gtk.STOCK_SAVE, _("_Save"), "<Control>S", _("Save this circuit."), self.on_action_save_pressed),
 
100
                        ("saveas",    Gtk.STOCK_SAVE_AS, _("Save _As..."), "<Shift><Control>S", _("Save this circuit with a new name."), self.on_action_saveas_pressed),
 
101
                        ("quit",      Gtk.STOCK_QUIT, _("_Quit"), "<Control>Q", _("Close this application."), self.on_action_quit_pressed),
 
102
                        ("undo",      Gtk.STOCK_UNDO, _("_Undo"), "<Control>Z", _("Undo the previous action."), self.on_action_undo_pressed),
 
103
                        ("redo",      Gtk.STOCK_REDO, _("_Redo"), "<Shift><Control>Z", _("Redo the action that you have canceled."), self.on_action_redo_pressed),
 
104
                        ("cut",       Gtk.STOCK_CUT, _("Cu_t"), "<Control>X", _("Cut selected components."), None),
 
105
                        ("copy",      Gtk.STOCK_COPY, _("_Copy"), "<Control>C", _("Copy selected components."), self.on_action_copy_pressed),
 
106
                        ("paste",     Gtk.STOCK_PASTE, _("_Paste"), "<Control>V", _("Paste copied components."), self.on_action_paste_pressed),
 
107
                        ("delete",    Gtk.STOCK_DELETE, _("_Delete"), "Delete", _("Delete selected components."), self.on_action_delete_pressed),
 
108
                        ("trans",     None, _("Translate This Application..."), None, _("Connect to the Launchpad website to help translate this application."), self.on_action_translate_pressed),
 
109
                        ("report",    None, _("Report a Problem..."), None, _("Connect to the Launchpad website to report a problem of this application."), self.on_action_bug_pressed),
 
110
                        ("about",     Gtk.STOCK_ABOUT, _("_About"), None, _("Show about dialog."), self.on_action_about_pressed),
 
111
                        ("file",      None, _("_File")),
 
112
                        ("edit",      None, _("_Edit")),
 
113
                        ("add",       None, _("_Add")),
 
114
                        ("simulate",  None, _("_Simulate")),
 
115
                        ("help",      None, _("_Help"))
 
116
                ]
 
117
                toggle_actions = [
 
118
                        ("property",  Gtk.STOCK_PREFERENCES, _("_Properties"), "<Control>N", _("Show property dialog."), self.on_action_property_toggled),
 
119
                        ("components", None, _("_Components..."), "<Control>A", _("Show components window."), self.on_btn_add_components_toggled),
 
120
                        ("net",       None, _("_Net"), "<Control>E", _("Add nets to this circuit."), self.on_action_net_toggled),
 
121
                        ("run",       Gtk.STOCK_MEDIA_PLAY, _("_Run"), "F5", _("Run and simulate this circuit."), self.on_action_play_toggled),
 
122
                        ("chart",     None, _("_Timing Chart"), "<Control>T", _("Show timing chart window."), self.on_action_timingchart_pressed),
 
123
                ]
 
124
                self.menubar = Gtk.Menu()
 
125
 
 
126
                actiongroup.add_actions(actions)
 
127
                actiongroup.add_toggle_actions(toggle_actions)
 
128
                
 
129
                self.action_undo = actiongroup.get_action("undo")
 
130
                self.action_redo = actiongroup.get_action("redo")
 
131
                self.action_cut = actiongroup.get_action("cut")
 
132
                self.action_copy = actiongroup.get_action("copy")
 
133
                self.action_paste = actiongroup.get_action("paste")
 
134
                self.action_delete = actiongroup.get_action("delete")
 
135
                self.action_property = actiongroup.get_action("property")
 
136
                self.action_components = actiongroup.get_action("components")
 
137
                self.action_net = actiongroup.get_action("net")
 
138
                self.action_run = actiongroup.get_action("run")
 
139
                self.action_chart = actiongroup.get_action("chart")
 
140
                
 
141
                self.action_undo.set_sensitive(False)
 
142
                self.action_redo.set_sensitive(False)
 
143
                self.action_cut.set_sensitive(False)
 
144
                self.action_copy.set_sensitive(False)
 
145
                self.action_delete.set_sensitive(False)
 
146
                self.action_chart.set_sensitive(False)
 
147
 
 
148
                uimanager = Gtk.UIManager()
 
149
                uimanager.add_ui_from_string(menu_xml)
 
150
                self.add_accel_group(uimanager.get_accel_group())
 
151
                uimanager.insert_action_group(actiongroup)
 
152
 
 
153
                menubar = uimanager.get_widget("/MenuBar")
 
154
                box.pack_start(menubar, False, False, 0)
 
155
 
 
156
                toolbar = uimanager.get_widget("/ToolBar")
 
157
                toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
 
158
                box.pack_start(toolbar, False, False, 0)
 
159
 
 
160
                action = actiongroup.get_action('components')
 
161
                action.set_icon_name("add-component")
 
162
                action = actiongroup.get_action('net')
 
163
                action.set_icon_name("add-net")
 
164
                
 
165
                # Draw area
 
166
                self.drawarea = DrawArea(self)
 
167
                self.drawarea.circuit = self.circuit
 
168
                self.drawarea.pushed_component = comp_dict[const.component_none]
 
169
                box.pack_start(self.drawarea, False, True, 0)
 
170
                
 
171
                # Status bar
 
172
                self.statusbar = Gtk.Statusbar()
 
173
                box.pack_start(self.statusbar, False, False, 0)
 
174
 
 
175
                self.add(box)
 
176
                
 
177
                # Component window
 
178
                self.comp_window = ComponentWindow(self)
 
179
                
 
180
                # Property window
 
181
                self.prop_window = PropertyWindow(self)
 
182
                
 
183
                # Timing chart window
 
184
                self.chart_window = TimingChartWindow(self)
 
185
                
 
186
                # About dialog
 
187
                self.about_dialog = Gtk.AboutDialog()
 
188
                self.about_dialog.set_logo(GdkPixbuf.Pixbuf.new_from_file(config.DATADIR+"/images/glogic.png"))
 
189
                self.about_dialog.set_program_name(const.app_name)
 
190
                self.about_dialog.set_version(config.VERSION)
 
191
                self.about_dialog.set_comments(const.description)
 
192
                self.about_dialog.set_copyright(const.copyright)
 
193
                self.about_dialog.set_website(const.website)
 
194
                self.about_dialog.set_license(const.license)
 
195
                self.about_dialog.set_authors(const.developer)
 
196
                tr_credits = _("translator-credits")
 
197
                if tr_credits != "translator-credits":
 
198
                        self.about_dialog.set_translator_credits(tr_credits)
 
199
                
 
200
                # Connect events
 
201
                self.connect("delete-event", self.on_window_delete)
 
202
        
 
203
        def on_action_about_pressed(self, widget):
 
204
                self.about_dialog.run()
 
205
                self.about_dialog.hide()
 
206
        
 
207
        def on_action_new_pressed(self, widget):
 
208
                if self.check_modified():
 
209
                        return
 
210
                        
 
211
                self.set_title("%s - wxLogic" % const.text_notitle)
 
212
                self.reset_frame()
 
213
                self.circuit.reset_circuit()
 
214
                self.drawarea.redraw = True
 
215
                self.drawarea.queue_draw()
 
216
                
 
217
        def add_filters(self, dialog):
 
218
                filter_wxl = Gtk.FileFilter()
 
219
                filter_wxl.set_name(_("gLogic files (*.glc)"))
 
220
                filter_wxl.add_pattern("*.glc")
 
221
                dialog.add_filter(filter_wxl)
 
222
                filter_any = Gtk.FileFilter()
 
223
                filter_any.set_name(_("All files"))
 
224
                filter_any.add_pattern("*")
 
225
                dialog.add_filter(filter_any)
 
226
                
 
227
        def reset_frame(self):
 
228
                self.comp_window.uncheck_all_buttons()
 
229
                # reset prop window
 
230
                self.statusbar.push(0, "")
 
231
                self.running_mode = False
 
232
                self.comp_window.checked_button = const.component_none
 
233
                self.drawarea.pushed_component = comp_dict[const.component_none]
 
234
                self.action_undo.set_sensitive(False)
 
235
                self.action_redo.set_sensitive(False)
 
236
                self.action_cut.set_sensitive(False)
 
237
                self.action_copy.set_sensitive(False)
 
238
                self.action_delete.set_sensitive(False)
 
239
                self.action_net.set_active(False)
 
240
                self.action_run.set_active(False)
 
241
                
 
242
        def on_action_open_pressed(self, widget):
 
243
                if self.check_modified():
 
244
                        return
 
245
                while True:
 
246
                        dialog = Gtk.FileChooserDialog(_("Open file"), self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT))
 
247
                        dialog.set_transient_for(self)
 
248
                        self.add_filters(dialog)
 
249
                        if dialog.run() == Gtk.ResponseType.ACCEPT:
 
250
                                filepath = dialog.get_filename()
 
251
                        else:
 
252
                                break
 
253
                                
 
254
                        if not self.circuit.open_file(filepath):
 
255
                                self.reset_frame()
 
256
                                self.drawarea.redraw = True
 
257
                                self.drawarea.queue_draw()
 
258
                                break
 
259
                                
 
260
                dialog.destroy()
 
261
                
 
262
        def overwrite_save(self):
 
263
                if self.circuit.filepath == "":
 
264
                        return self.rename_save()
 
265
                else:
 
266
                        if self.circuit.save_file(self.circuit.filepath):
 
267
                                return self.rename_save()
 
268
                        return False
 
269
                        
 
270
        def rename_save(self):
 
271
                chooser = Gtk.FileChooserDialog(_("Save file"), self, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT), flags=Gtk.DialogFlags.MODAL)
 
272
                chooser.set_transient_for(self)
 
273
                chooser.set_modal(True) 
 
274
                while True:
 
275
                        self.add_filters(chooser)
 
276
                        if chooser.run() == Gtk.ResponseType.ACCEPT:
 
277
                                filepath = chooser.get_filename()
 
278
                                filter_name = chooser.get_filter().get_name()
 
279
                                if filter_name == _("gLogic files (*.glc)"):
 
280
                                        if not "." in os.path.basename(filepath):
 
281
                                                filepath += ".glc"
 
282
                                                
 
283
                                if os.path.exists(filepath):
 
284
                                        dialog = Gtk.MessageDialog(chooser, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, _("Overwrite to the existing file?"))
 
285
                                        dialog.format_secondary_text(_("The file already exist. Overwrite it?"))
 
286
                                        retval = dialog.run()
 
287
                                        dialog.destroy()
 
288
                                        if retval == Gtk.ResponseType.NO:
 
289
                                                continue
 
290
                                
 
291
                        else:
 
292
                                chooser.destroy()
 
293
                                return True
 
294
                                
 
295
                        if not self.circuit.save_file(filepath):
 
296
                                chooser.destroy()
 
297
                                return False
 
298
        
 
299
        def on_action_save_pressed(self, widget):
 
300
                self.overwrite_save()
 
301
 
 
302
        def on_action_saveas_pressed(self, widget):
 
303
                self.rename_save()
 
304
                
 
305
        def on_action_quit_pressed(self, widget):
 
306
                event = Gdk.Event(Gdk.EventType.DELETE)
 
307
                self.emit("delete-event", event)
 
308
                
 
309
        def check_modified(self):
 
310
                if self.circuit.need_save:
 
311
                        dialog = Gtk.MessageDialog(self, Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, Gtk.ButtonsType.YES_NO, _("Save the modified schematics?"))
 
312
                        dialog.format_secondary_text(_("The schematics was modifed. Save the changes before closing?"))
 
313
                        retval = dialog.run()
 
314
                        dialog.destroy()
 
315
                        if retval == Gtk.ResponseType.YES:
 
316
                                return self.overwrite_save()
 
317
                        elif retval == Gtk.ResponseType.NO:
 
318
                                return False
 
319
                        else:
 
320
                                return True
 
321
                return False
 
322
 
 
323
        def on_btn_add_components_toggled(self, widget):
 
324
                if widget.get_active():
 
325
                        self.comp_window.show_all()
 
326
                else:
 
327
                        self.comp_window.hide()
 
328
 
 
329
        def on_window_delete(self, widget, event):
 
330
                if self.check_modified():
 
331
                        return True
 
332
                Gtk.main_quit()
 
333
                return False
 
334
        
 
335
        def on_action_net_toggled(self, widget):
 
336
                if widget.get_active():
 
337
                        self.comp_window.uncheck_all_buttons()
 
338
                        widget.set_active(True)
 
339
                        self.comp_window.checked_button = const.component_net
 
340
                        self.drawarea.pushed_component = comp_dict[const.component_net]
 
341
                elif self.comp_window.checked_button == const.component_net:
 
342
                        self.comp_window.checked_button = const.component_none
 
343
                        self.drawarea.pushed_component = comp_dict[const.component_none]
 
344
                self.drawarea.queue_draw()
 
345
        
 
346
        def on_action_play_toggled(self, widget):
 
347
                if self.running_mode:
 
348
                        self.running_mode = False
 
349
                        if self.circuit.action_count > 0:
 
350
                                self.action_undo.set_sensitive(True)
 
351
                        if self.circuit.action_count < len(self.circuit.components_history) - 1:
 
352
                                self.action_redo.set_sensitive(True)
 
353
                        self.action_property.set_sensitive(True)
 
354
                        self.action_components.set_sensitive(True)
 
355
                        self.action_net.set_sensitive(True)
 
356
                        self.action_chart.set_sensitive(False)
 
357
                        self.action_chart.set_active(False)
 
358
                        self.chart_window.hide()
 
359
                        self.statusbar.push(0, "")
 
360
                else:
 
361
                        self.running_mode = True
 
362
                        self.circuit.selected_components = []
 
363
                        self.action_undo.set_sensitive(False)
 
364
                        self.action_redo.set_sensitive(False)
 
365
                        self.action_cut.set_sensitive(False)
 
366
                        self.action_copy.set_sensitive(False)
 
367
                        self.action_delete.set_sensitive(False)
 
368
                        self.action_property.set_sensitive(False)
 
369
                        self.action_property.set_active(False)
 
370
                        self.action_components.set_sensitive(False)
 
371
                        self.action_components.set_active(False)
 
372
                        self.action_net.set_sensitive(False)
 
373
                        self.action_chart.set_sensitive(True)
 
374
                        self.comp_window.hide()
 
375
                        self.prop_window.hide()
 
376
                        self.comp_window.checked_button = const.component_none
 
377
                        self.drawarea.pushed_component = comp_dict[const.component_none]
 
378
                        self.circuit.analyze_connections()
 
379
                        self.circuit.initialize_logic()
 
380
                        if not self.circuit.analyze_logic():
 
381
                                self.chart_window.chartarea.createChart()
 
382
                self.drawarea.redraw = True
 
383
                self.drawarea.queue_draw()
 
384
                
 
385
        def on_action_copy_pressed(self, widget):
 
386
                self.circuit.copy()
 
387
        
 
388
        def on_action_paste_pressed(self, widget):
 
389
                self.circuit.paste()
 
390
        
 
391
        def on_action_undo_pressed(self, widget):
 
392
                self.circuit.undo()
 
393
                if self.circuit.action_count == 0:
 
394
                        self.action_undo.set_sensitive(False)
 
395
                self.action_redo.set_sensitive(True)
 
396
                self.action_cut.set_sensitive(False)
 
397
                self.action_copy.set_sensitive(False)
 
398
                self.action_delete.set_sensitive(False)
 
399
                self.drawarea.redraw = True
 
400
                self.drawarea.queue_draw()
 
401
                
 
402
        def on_action_redo_pressed(self, widget):
 
403
                self.circuit.redo()
 
404
                self.action_undo.set_sensitive(True)
 
405
                if self.circuit.action_count == len(self.circuit.components_history) - 1:
 
406
                        self.action_redo.set_sensitive(False)
 
407
                self.action_cut.set_sensitive(False)
 
408
                self.action_copy.set_sensitive(False)
 
409
                self.action_delete.set_sensitive(False)
 
410
                self.drawarea.redraw = True
 
411
                self.drawarea.queue_draw()
 
412
        
 
413
        def on_action_delete_pressed(self, widget):
 
414
                self.circuit.remove_selected_component()
 
415
                self.drawarea.nearest_component = None
 
416
                self.drawarea.preselected_component = None
 
417
                self.circuit.push_history()
 
418
                self.action_undo.set_sensitive(True)
 
419
                self.action_redo.set_sensitive(False)
 
420
                self.action_cut.set_sensitive(False)
 
421
                self.action_copy.set_sensitive(False)
 
422
                self.action_delete.set_sensitive(False)
 
423
                self.drawarea.redraw = True
 
424
                self.drawarea.queue_draw()
 
425
        
 
426
        def on_action_property_toggled(self, widget):
 
427
                if widget.get_active():
 
428
                        self.drawarea.set_selected_component_to_prop_window()
 
429
                        self.prop_window.show_all()
 
430
                else:
 
431
                        self.prop_window.hide()
 
432
                        
 
433
        def on_action_translate_pressed(self, widget):
 
434
                webbrowser.open(const.devel_translate)
 
435
                
 
436
        def on_action_bug_pressed(self, widget):
 
437
                webbrowser.open(const.devel_bug)
 
438
                
 
439
        def on_action_timingchart_pressed(self, widget):
 
440
                if widget.get_active():
 
441
                        self.chart_window.show_all()
 
442
                else:
 
443
                        self.chart_window.hide()